2006-11-09 14:32:27 +08:00
|
|
|
//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2006-11-09 14:32:27 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements semantic analysis for declarations.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2006-11-10 13:29:30 +08:00
|
|
|
#include "Sema.h"
|
2008-07-03 12:20:39 +08:00
|
|
|
#include "clang/AST/APValue.h"
|
2008-02-06 08:51:33 +08:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
2006-12-03 16:41:30 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2008-08-11 13:35:13 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2008-06-27 02:38:35 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2006-11-20 07:16:18 +08:00
|
|
|
#include "clang/Parse/DeclSpec.h"
|
2008-08-11 11:45:03 +08:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2007-01-28 16:20:04 +08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2008-01-31 07:46:05 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
|
|
|
// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
|
2008-02-06 08:51:33 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2008-01-31 07:46:05 +08:00
|
|
|
#include "clang/Lex/HeaderSearch.h"
|
2007-01-27 14:24:01 +08:00
|
|
|
#include "llvm/ADT/SmallSet.h"
|
2008-12-12 04:41:00 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2008-12-24 05:05:05 +08:00
|
|
|
#include <algorithm>
|
|
|
|
#include <functional>
|
2008-12-12 04:41:00 +08:00
|
|
|
|
2006-11-09 14:32:27 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2008-11-18 04:34:05 +08:00
|
|
|
Sema::TypeTy *Sema::isTypeName(IdentifierInfo &II, Scope *S,
|
2008-11-09 00:45:02 +08:00
|
|
|
const CXXScopeSpec *SS) {
|
2008-11-09 01:17:31 +08:00
|
|
|
DeclContext *DC = 0;
|
|
|
|
if (SS) {
|
|
|
|
if (SS->isInvalid())
|
|
|
|
return 0;
|
|
|
|
DC = static_cast<DeclContext*>(SS->getScopeRep());
|
|
|
|
}
|
|
|
|
Decl *IIDecl = LookupDecl(&II, Decl::IDNS_Ordinary, S, DC, false);
|
2008-04-02 22:35:35 +08:00
|
|
|
|
2008-04-14 05:07:44 +08:00
|
|
|
if (IIDecl && (isa<TypedefDecl>(IIDecl) ||
|
|
|
|
isa<ObjCInterfaceDecl>(IIDecl) ||
|
2008-12-06 02:15:24 +08:00
|
|
|
isa<TagDecl>(IIDecl) ||
|
|
|
|
isa<TemplateTypeParmDecl>(IIDecl)))
|
2007-10-13 00:34:10 +08:00
|
|
|
return IIDecl;
|
2007-09-07 05:24:23 +08:00
|
|
|
return 0;
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2008-11-09 01:17:31 +08:00
|
|
|
DeclContext *Sema::getContainingDC(DeclContext *DC) {
|
2008-07-01 18:37:29 +08:00
|
|
|
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
|
2008-11-09 01:17:31 +08:00
|
|
|
// A C++ out-of-line method will return to the file declaration context.
|
2008-11-10 07:41:00 +08:00
|
|
|
if (MD->isOutOfLineDefinition())
|
|
|
|
return MD->getLexicalDeclContext();
|
2008-11-09 01:17:31 +08:00
|
|
|
|
|
|
|
// A C++ inline method is parsed *after* the topmost class it was declared in
|
|
|
|
// is fully parsed (it's "complete").
|
|
|
|
// The parsing of a C++ inline method happens at the declaration context of
|
2008-11-20 02:01:13 +08:00
|
|
|
// the topmost (non-nested) class it is lexically declared in.
|
2008-07-01 18:37:29 +08:00
|
|
|
assert(isa<CXXRecordDecl>(MD->getParent()) && "C++ method not in Record.");
|
|
|
|
DC = MD->getParent();
|
2008-11-20 02:01:13 +08:00
|
|
|
while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent()))
|
2008-07-01 18:37:29 +08:00
|
|
|
DC = RD;
|
|
|
|
|
|
|
|
// Return the declaration context of the topmost class the inline method is
|
|
|
|
// declared in.
|
|
|
|
return DC;
|
|
|
|
}
|
|
|
|
|
2008-11-10 07:41:00 +08:00
|
|
|
if (isa<ObjCMethodDecl>(DC))
|
|
|
|
return Context.getTranslationUnitDecl();
|
|
|
|
|
|
|
|
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(DC))
|
|
|
|
return SD->getLexicalDeclContext();
|
2008-11-09 01:17:31 +08:00
|
|
|
|
2008-11-20 02:01:13 +08:00
|
|
|
return DC->getLexicalParent();
|
2008-07-01 18:37:29 +08:00
|
|
|
}
|
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
void Sema::PushDeclContext(Scope *S, DeclContext *DC) {
|
2008-11-09 01:17:31 +08:00
|
|
|
assert(getContainingDC(DC) == CurContext &&
|
2008-12-08 15:14:51 +08:00
|
|
|
"The next DeclContext should be lexically contained in the current one.");
|
2008-04-23 02:39:57 +08:00
|
|
|
CurContext = DC;
|
2008-12-12 00:49:14 +08:00
|
|
|
S->setEntity(DC);
|
2008-04-04 14:12:32 +08:00
|
|
|
}
|
|
|
|
|
2008-04-06 12:47:34 +08:00
|
|
|
void Sema::PopDeclContext() {
|
|
|
|
assert(CurContext && "DeclContext imbalance!");
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2008-11-09 01:17:31 +08:00
|
|
|
CurContext = getContainingDC(CurContext);
|
2008-04-04 14:12:32 +08:00
|
|
|
}
|
|
|
|
|
2008-04-12 08:47:19 +08:00
|
|
|
/// Add this decl to the scope shadowed decl chains.
|
|
|
|
void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
|
|
|
|
S->AddDecl(D);
|
2008-05-10 07:39:43 +08:00
|
|
|
|
2008-12-24 05:05:05 +08:00
|
|
|
// Add scoped declarations into their context, so that they can be
|
|
|
|
// found later. Declarations without a context won't be inserted
|
|
|
|
// into any context.
|
|
|
|
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
|
|
|
|
CurContext->addDecl(Context, SD);
|
|
|
|
|
2008-05-10 07:39:43 +08:00
|
|
|
// C++ [basic.scope]p4:
|
|
|
|
// -- exactly one declaration shall declare a class name or
|
|
|
|
// enumeration name that is not a typedef name and the other
|
|
|
|
// declarations shall all refer to the same object or
|
|
|
|
// enumerator, or all refer to functions and function templates;
|
|
|
|
// in this case the class name or enumeration name is hidden.
|
|
|
|
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
|
|
|
|
// We are pushing the name of a tag (enum or class).
|
2008-12-12 00:49:14 +08:00
|
|
|
if (CurContext == TD->getDeclContext()) {
|
|
|
|
// We're pushing the tag into the current context, which might
|
|
|
|
// require some reshuffling in the identifier resolver.
|
|
|
|
IdentifierResolver::iterator
|
2008-12-24 05:05:05 +08:00
|
|
|
I = IdResolver.begin(TD->getDeclName(), CurContext,
|
|
|
|
false/*LookInParentCtx*/),
|
|
|
|
IEnd = IdResolver.end();
|
|
|
|
if (I != IEnd && isDeclInScope(*I, CurContext, S)) {
|
|
|
|
NamedDecl *PrevDecl = *I;
|
|
|
|
for (; I != IEnd && isDeclInScope(*I, CurContext, S);
|
|
|
|
PrevDecl = *I, ++I) {
|
|
|
|
if (TD->declarationReplaces(*I)) {
|
|
|
|
// This is a redeclaration. Remove it from the chain and
|
|
|
|
// break out, so that we'll add in the shadowed
|
|
|
|
// declaration.
|
|
|
|
S->RemoveDecl(*I);
|
|
|
|
if (PrevDecl == *I) {
|
|
|
|
IdResolver.RemoveDecl(*I);
|
|
|
|
IdResolver.AddDecl(TD);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
IdResolver.RemoveDecl(*I);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// There is already a declaration with the same name in the same
|
|
|
|
// scope, which is not a tag declaration. It must be found
|
|
|
|
// before we find the new declaration, so insert the new
|
|
|
|
// declaration at the end of the chain.
|
|
|
|
IdResolver.AddShadowedDecl(TD, PrevDecl);
|
|
|
|
|
|
|
|
return;
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
2008-10-22 00:13:35 +08:00
|
|
|
}
|
2008-10-23 07:08:24 +08:00
|
|
|
} else if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
|
2008-10-22 00:13:35 +08:00
|
|
|
// We are pushing the name of a function, which might be an
|
|
|
|
// overloaded name.
|
2008-12-12 00:49:14 +08:00
|
|
|
FunctionDecl *FD = cast<FunctionDecl>(D);
|
2008-12-24 05:05:05 +08:00
|
|
|
IdentifierResolver::iterator Redecl
|
|
|
|
= std::find_if(IdResolver.begin(FD->getDeclName(), CurContext,
|
|
|
|
false/*LookInParentCtx*/),
|
|
|
|
IdResolver.end(),
|
|
|
|
std::bind1st(std::mem_fun(&ScopedDecl::declarationReplaces),
|
|
|
|
FD));
|
|
|
|
if (Redecl != IdResolver.end()) {
|
|
|
|
// There is already a declaration of a function on our
|
|
|
|
// IdResolver chain. Replace it with this declaration.
|
|
|
|
S->RemoveDecl(*Redecl);
|
|
|
|
IdResolver.RemoveDecl(*Redecl);
|
2008-05-10 07:39:43 +08:00
|
|
|
}
|
|
|
|
}
|
2008-10-22 00:13:35 +08:00
|
|
|
|
2008-05-10 07:39:43 +08:00
|
|
|
IdResolver.AddDecl(D);
|
2008-04-12 08:47:19 +08:00
|
|
|
}
|
|
|
|
|
2007-10-10 06:01:59 +08:00
|
|
|
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
|
2007-08-26 14:24:45 +08:00
|
|
|
if (S->decl_empty()) return;
|
2008-12-06 02:15:24 +08:00
|
|
|
assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
|
|
|
|
"Scope shouldn't contain decls!");
|
2008-05-10 07:39:43 +08:00
|
|
|
|
2006-11-19 10:31:38 +08:00
|
|
|
for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
|
|
|
|
I != E; ++I) {
|
2007-09-14 02:10:37 +08:00
|
|
|
Decl *TmpD = static_cast<Decl*>(*I);
|
|
|
|
assert(TmpD && "This decl didn't get pushed??");
|
2008-06-10 09:32:09 +08:00
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
|
|
|
|
NamedDecl *D = cast<NamedDecl>(TmpD);
|
2008-06-10 09:32:09 +08:00
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
if (!D->getDeclName()) continue;
|
|
|
|
|
|
|
|
// Remove this name from our lexical scope.
|
|
|
|
IdResolver.RemoveDecl(D);
|
2006-11-19 10:31:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-02 07:04:06 +08:00
|
|
|
/// getObjCInterfaceDecl - Look up a for a class declaration in the scope.
|
|
|
|
/// return 0 if one not found.
|
|
|
|
ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
|
2008-04-03 02:30:49 +08:00
|
|
|
// The third "scope" argument is 0 since we aren't enabling lazy built-in
|
|
|
|
// creation from this context.
|
|
|
|
Decl *IDecl = LookupDecl(Id, Decl::IDNS_Ordinary, 0, false);
|
2007-10-13 03:38:20 +08:00
|
|
|
|
2008-04-02 22:35:35 +08:00
|
|
|
return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
|
2007-10-13 03:38:20 +08:00
|
|
|
}
|
|
|
|
|
2008-12-23 08:26:44 +08:00
|
|
|
/// MaybeConstructOverloadSet - Name lookup has determined that the
|
|
|
|
/// elements in [I, IEnd) have the name that we are looking for, and
|
|
|
|
/// *I is a match for the namespace. This routine returns an
|
|
|
|
/// appropriate Decl for name lookup, which may either be *I or an
|
|
|
|
/// OverloadeFunctionDecl that represents the overloaded functions in
|
|
|
|
/// [I, IEnd).
|
|
|
|
///
|
|
|
|
/// The existance of this routine is temporary; LookupDecl should
|
|
|
|
/// probably be able to return multiple results, to deal with cases of
|
|
|
|
/// ambiguity and overloaded functions without needing to create a
|
|
|
|
/// Decl node.
|
2008-12-24 05:05:05 +08:00
|
|
|
template<typename DeclIterator>
|
2008-12-23 08:26:44 +08:00
|
|
|
static Decl *
|
2008-12-24 05:05:05 +08:00
|
|
|
MaybeConstructOverloadSet(ASTContext &Context,
|
|
|
|
DeclIterator I, DeclIterator IEnd) {
|
2008-12-23 08:26:44 +08:00
|
|
|
assert(I != IEnd && "Iterator range cannot be empty");
|
|
|
|
assert(!isa<OverloadedFunctionDecl>(*I) &&
|
|
|
|
"Cannot have an overloaded function");
|
|
|
|
|
|
|
|
if (isa<FunctionDecl>(*I)) {
|
|
|
|
// If we found a function, there might be more functions. If
|
|
|
|
// so, collect them into an overload set.
|
2008-12-24 05:05:05 +08:00
|
|
|
DeclIterator Last = I;
|
2008-12-23 08:26:44 +08:00
|
|
|
OverloadedFunctionDecl *Ovl = 0;
|
|
|
|
for (++Last; Last != IEnd && isa<FunctionDecl>(*Last); ++Last) {
|
|
|
|
if (!Ovl) {
|
|
|
|
// FIXME: We leak this overload set. Eventually, we want to
|
|
|
|
// stop building the declarations for these overload sets, so
|
|
|
|
// there will be nothing to leak.
|
|
|
|
Ovl = OverloadedFunctionDecl::Create(Context,
|
2008-12-24 05:05:05 +08:00
|
|
|
cast<ScopedDecl>(*I)->getDeclContext(),
|
2008-12-23 08:26:44 +08:00
|
|
|
(*I)->getDeclName());
|
|
|
|
Ovl->addOverload(cast<FunctionDecl>(*I));
|
|
|
|
}
|
|
|
|
Ovl->addOverload(cast<FunctionDecl>(*Last));
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we had more than one function, we built an overload
|
|
|
|
// set. Return it.
|
|
|
|
if (Ovl)
|
|
|
|
return Ovl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *I;
|
|
|
|
}
|
|
|
|
|
2008-04-02 07:04:06 +08:00
|
|
|
/// LookupDecl - Look up the inner-most declaration in the specified
|
2008-12-30 11:27:21 +08:00
|
|
|
/// namespace. NamespaceNameOnly - during lookup only namespace names
|
|
|
|
/// are considered as required in C++ [basic.lookup.udir] 3.4.6.p1
|
|
|
|
/// 'When looking up a namespace-name in a using-directive or
|
|
|
|
/// namespace-alias-definition, only namespace names are considered.'
|
2008-11-18 04:34:05 +08:00
|
|
|
Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
|
2008-11-11 19:37:55 +08:00
|
|
|
const DeclContext *LookupCtx,
|
2008-12-12 00:49:14 +08:00
|
|
|
bool enableLazyBuiltinCreation,
|
2008-12-30 11:27:21 +08:00
|
|
|
bool LookInParent,
|
|
|
|
bool NamespaceNameOnly) {
|
2008-11-18 04:34:05 +08:00
|
|
|
if (!Name) return 0;
|
2008-04-14 05:07:44 +08:00
|
|
|
unsigned NS = NSI;
|
|
|
|
if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
|
|
|
|
NS |= Decl::IDNS_Tag;
|
2008-04-11 15:00:53 +08:00
|
|
|
|
2008-12-12 04:41:00 +08:00
|
|
|
if (LookupCtx == 0 &&
|
|
|
|
(!getLangOptions().CPlusPlus || (NS == Decl::IDNS_Label))) {
|
|
|
|
// Unqualified name lookup in C/Objective-C and name lookup for
|
|
|
|
// labels in C++ is purely lexical, so search in the
|
|
|
|
// declarations attached to the name.
|
|
|
|
assert(!LookupCtx && "Can't perform qualified name lookup here");
|
2008-12-30 11:27:21 +08:00
|
|
|
assert(!NamespaceNameOnly && "Can't perform namespace name lookup here");
|
2008-12-12 04:41:00 +08:00
|
|
|
IdentifierResolver::iterator I
|
|
|
|
= IdResolver.begin(Name, CurContext, LookInParent);
|
|
|
|
|
|
|
|
// Scan up the scope chain looking for a decl that matches this
|
|
|
|
// identifier that is in the appropriate namespace. This search
|
|
|
|
// should not take long, as shadowing of names is uncommon, and
|
|
|
|
// deep shadowing is extremely uncommon.
|
|
|
|
for (; I != IdResolver.end(); ++I)
|
|
|
|
if ((*I)->getIdentifierNamespace() & NS)
|
2008-12-30 11:27:21 +08:00
|
|
|
return *I;
|
2008-12-12 04:41:00 +08:00
|
|
|
} else if (LookupCtx) {
|
2008-12-12 00:49:14 +08:00
|
|
|
// Perform qualified name lookup into the LookupCtx.
|
|
|
|
// FIXME: Will need to look into base classes and such.
|
2008-12-12 04:41:00 +08:00
|
|
|
DeclContext::lookup_const_iterator I, E;
|
|
|
|
for (llvm::tie(I, E) = LookupCtx->lookup(Context, Name); I != E; ++I)
|
2008-12-30 11:27:21 +08:00
|
|
|
if ((*I)->getIdentifierNamespace() & NS) {
|
|
|
|
if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) {
|
|
|
|
// Skip non-namespace name.
|
|
|
|
} else {
|
|
|
|
return MaybeConstructOverloadSet(Context, I, E);
|
|
|
|
}
|
|
|
|
}
|
2008-12-12 04:41:00 +08:00
|
|
|
} else {
|
2008-12-12 00:49:14 +08:00
|
|
|
// Name lookup for ordinary names and tag names in C++ requires
|
|
|
|
// looking into scopes that aren't strictly lexical, and
|
|
|
|
// therefore we walk through the context as well as walking
|
|
|
|
// through the scopes.
|
|
|
|
IdentifierResolver::iterator
|
|
|
|
I = IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/),
|
|
|
|
IEnd = IdResolver.end();
|
|
|
|
for (; S; S = S->getParent()) {
|
|
|
|
// Check whether the IdResolver has anything in this scope.
|
|
|
|
// FIXME: The isDeclScope check could be expensive. Can we do better?
|
2008-12-24 05:05:05 +08:00
|
|
|
for (; I != IEnd && S->isDeclScope(*I); ++I) {
|
|
|
|
if ((*I)->getIdentifierNamespace() & NS) {
|
2008-12-30 11:27:21 +08:00
|
|
|
if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) {
|
|
|
|
// Skip non-namespace name.
|
|
|
|
} else {
|
|
|
|
// We found something. Look for anything else in our scope
|
|
|
|
// with this same name and in an acceptable identifier
|
|
|
|
// namespace, so that we can construct an overload set if we
|
|
|
|
// need to.
|
|
|
|
IdentifierResolver::iterator LastI = I;
|
|
|
|
for (++LastI; LastI != IEnd; ++LastI) {
|
|
|
|
if (((*LastI)->getIdentifierNamespace() & NS) == 0 ||
|
|
|
|
!S->isDeclScope(*LastI))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return MaybeConstructOverloadSet(Context, I, LastI);
|
2008-12-24 05:05:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
|
|
|
|
// If there is an entity associated with this scope, it's a
|
|
|
|
// DeclContext. We might need to perform qualified lookup into
|
|
|
|
// it.
|
|
|
|
DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
|
|
|
|
while (Ctx && Ctx->isFunctionOrMethod())
|
|
|
|
Ctx = Ctx->getParent();
|
|
|
|
while (Ctx && (Ctx->isNamespace() || Ctx->isCXXRecord())) {
|
|
|
|
// Look for declarations of this name in this scope.
|
2008-12-12 04:41:00 +08:00
|
|
|
DeclContext::lookup_const_iterator I, E;
|
|
|
|
for (llvm::tie(I, E) = Ctx->lookup(Context, Name); I != E; ++I) {
|
2008-12-12 00:49:14 +08:00
|
|
|
// FIXME: Cache this result in the IdResolver
|
2008-12-30 11:27:21 +08:00
|
|
|
if ((*I)->getIdentifierNamespace() & NS) {
|
|
|
|
if (NamespaceNameOnly && !isa<NamespaceDecl>(*I)) {}
|
|
|
|
else return MaybeConstructOverloadSet(Context, I, E);
|
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Ctx = Ctx->getParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!LookInParent)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2008-04-11 15:00:53 +08:00
|
|
|
|
2007-01-28 16:20:04 +08:00
|
|
|
// If we didn't find a use of this identifier, and if the identifier
|
|
|
|
// corresponds to a compiler builtin, create the decl object for the builtin
|
|
|
|
// now, injecting it into translation unit scope, and return it.
|
2008-04-14 05:07:44 +08:00
|
|
|
if (NS & Decl::IDNS_Ordinary) {
|
2008-11-18 04:34:05 +08:00
|
|
|
IdentifierInfo *II = Name.getAsIdentifierInfo();
|
|
|
|
if (enableLazyBuiltinCreation && II &&
|
2008-11-09 01:17:31 +08:00
|
|
|
(LookupCtx == 0 || isa<TranslationUnitDecl>(LookupCtx))) {
|
2008-04-02 22:35:35 +08:00
|
|
|
// If this is a builtin on this (or all) targets, create the decl.
|
|
|
|
if (unsigned BuiltinID = II->getBuiltinID())
|
|
|
|
return LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, S);
|
|
|
|
}
|
2008-11-18 04:34:05 +08:00
|
|
|
if (getLangOptions().ObjC1 && II) {
|
2008-04-02 07:04:06 +08:00
|
|
|
// @interface and @compatibility_alias introduce typedef-like names.
|
|
|
|
// Unlike typedef's, they can only be introduced at file-scope (and are
|
2008-04-02 08:39:51 +08:00
|
|
|
// therefore not scoped decls). They can, however, be shadowed by
|
2008-04-02 07:04:06 +08:00
|
|
|
// other names in IDNS_Ordinary.
|
2008-04-03 02:30:49 +08:00
|
|
|
ObjCInterfaceDeclsTy::iterator IDI = ObjCInterfaceDecls.find(II);
|
|
|
|
if (IDI != ObjCInterfaceDecls.end())
|
|
|
|
return IDI->second;
|
2008-04-02 07:04:06 +08:00
|
|
|
ObjCAliasTy::iterator I = ObjCAliasDecls.find(II);
|
|
|
|
if (I != ObjCAliasDecls.end())
|
|
|
|
return I->second->getClassInterface();
|
|
|
|
}
|
2007-01-28 16:20:04 +08:00
|
|
|
}
|
2007-01-22 15:39:13 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-05-06 06:18:14 +08:00
|
|
|
void Sema::InitBuiltinVaListType() {
|
2007-10-16 04:28:48 +08:00
|
|
|
if (!Context.getBuiltinVaListType().isNull())
|
|
|
|
return;
|
|
|
|
|
|
|
|
IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list");
|
2008-04-02 22:35:35 +08:00
|
|
|
Decl *VaDecl = LookupDecl(VaIdent, Decl::IDNS_Ordinary, TUScope);
|
2007-10-19 06:17:45 +08:00
|
|
|
TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl);
|
2007-10-16 04:28:48 +08:00
|
|
|
Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef));
|
|
|
|
}
|
|
|
|
|
2007-01-28 16:20:04 +08:00
|
|
|
/// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope.
|
|
|
|
/// lazily create a decl for it.
|
2007-10-11 07:42:28 +08:00
|
|
|
ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
|
|
|
|
Scope *S) {
|
2007-01-28 16:20:04 +08:00
|
|
|
Builtin::ID BID = (Builtin::ID)bid;
|
|
|
|
|
2008-09-28 13:54:29 +08:00
|
|
|
if (Context.BuiltinInfo.hasVAListUse(BID))
|
2007-10-16 04:28:48 +08:00
|
|
|
InitBuiltinVaListType();
|
|
|
|
|
2007-10-11 09:00:40 +08:00
|
|
|
QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context);
|
2008-04-17 22:47:13 +08:00
|
|
|
FunctionDecl *New = FunctionDecl::Create(Context,
|
|
|
|
Context.getTranslationUnitDecl(),
|
2008-04-04 14:12:32 +08:00
|
|
|
SourceLocation(), II, R,
|
2008-03-16 05:24:04 +08:00
|
|
|
FunctionDecl::Extern, false, 0);
|
2007-01-28 16:20:04 +08:00
|
|
|
|
2008-05-06 06:18:14 +08:00
|
|
|
// Create Decl objects for each parameter, adding them to the
|
|
|
|
// FunctionDecl.
|
|
|
|
if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(R)) {
|
|
|
|
llvm::SmallVector<ParmVarDecl*, 16> Params;
|
|
|
|
for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i)
|
|
|
|
Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0,
|
|
|
|
FT->getArgType(i), VarDecl::None, 0,
|
|
|
|
0));
|
|
|
|
New->setParams(&Params[0], Params.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-04-11 15:00:53 +08:00
|
|
|
// TUScope is the translation-unit scope to insert this function into.
|
2008-05-10 07:39:43 +08:00
|
|
|
PushOnScopeChains(New, TUScope);
|
2007-01-28 16:20:04 +08:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
2008-11-11 19:37:55 +08:00
|
|
|
/// GetStdNamespace - This method gets the C++ "std" namespace. This is where
|
|
|
|
/// everything from the standard library is defined.
|
|
|
|
NamespaceDecl *Sema::GetStdNamespace() {
|
|
|
|
if (!StdNamespace) {
|
2008-11-20 13:45:14 +08:00
|
|
|
IdentifierInfo *StdIdent = &PP.getIdentifierTable().get("std");
|
2008-11-11 19:37:55 +08:00
|
|
|
DeclContext *Global = Context.getTranslationUnitDecl();
|
2008-11-20 13:45:14 +08:00
|
|
|
Decl *Std = LookupDecl(StdIdent, Decl::IDNS_Tag | Decl::IDNS_Ordinary,
|
2008-11-11 19:37:55 +08:00
|
|
|
0, Global, /*enableLazyBuiltinCreation=*/false);
|
|
|
|
StdNamespace = dyn_cast_or_null<NamespaceDecl>(Std);
|
|
|
|
}
|
|
|
|
return StdNamespace;
|
|
|
|
}
|
|
|
|
|
2007-01-28 03:27:06 +08:00
|
|
|
/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name
|
|
|
|
/// and scope as a previous declaration 'Old'. Figure out how to resolve this
|
|
|
|
/// situation, merging decls or emitting diagnostics as appropriate.
|
|
|
|
///
|
2008-04-02 07:04:06 +08:00
|
|
|
TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
|
2008-09-09 22:32:20 +08:00
|
|
|
// Allow multiple definitions for ObjC built-in typedefs.
|
|
|
|
// FIXME: Verify the underlying types are equivalent!
|
|
|
|
if (getLangOptions().ObjC1) {
|
2008-11-20 13:41:43 +08:00
|
|
|
const IdentifierInfo *TypeID = New->getIdentifier();
|
|
|
|
switch (TypeID->getLength()) {
|
|
|
|
default: break;
|
|
|
|
case 2:
|
|
|
|
if (!TypeID->isStr("id"))
|
|
|
|
break;
|
2008-09-09 22:32:20 +08:00
|
|
|
Context.setObjCIdType(New);
|
|
|
|
return New;
|
2008-11-20 13:41:43 +08:00
|
|
|
case 5:
|
|
|
|
if (!TypeID->isStr("Class"))
|
|
|
|
break;
|
2008-09-09 22:32:20 +08:00
|
|
|
Context.setObjCClassType(New);
|
|
|
|
return New;
|
2008-11-20 13:41:43 +08:00
|
|
|
case 3:
|
|
|
|
if (!TypeID->isStr("SEL"))
|
|
|
|
break;
|
2008-09-09 22:32:20 +08:00
|
|
|
Context.setObjCSelType(New);
|
|
|
|
return New;
|
2008-11-20 13:41:43 +08:00
|
|
|
case 8:
|
|
|
|
if (!TypeID->isStr("Protocol"))
|
|
|
|
break;
|
2008-09-09 22:32:20 +08:00
|
|
|
Context.setObjCProtoType(New->getUnderlyingType());
|
|
|
|
return New;
|
|
|
|
}
|
|
|
|
// Fall through - the typedef name was not a builtin type.
|
|
|
|
}
|
2007-01-28 03:32:14 +08:00
|
|
|
// Verify the old decl was also a typedef.
|
|
|
|
TypedefDecl *Old = dyn_cast<TypedefDecl>(OldD);
|
|
|
|
if (!Old) {
|
2008-11-20 14:13:02 +08:00
|
|
|
Diag(New->getLocation(), diag::err_redefinition_different_kind)
|
2008-11-24 05:45:46 +08:00
|
|
|
<< New->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(OldD->getLocation(), diag::note_previous_definition);
|
2007-01-28 03:32:14 +08:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
2008-07-26 02:44:27 +08:00
|
|
|
// If the typedef types are not identical, reject them in all languages and
|
|
|
|
// with any extensions enabled.
|
|
|
|
if (Old->getUnderlyingType() != New->getUnderlyingType() &&
|
|
|
|
Context.getCanonicalType(Old->getUnderlyingType()) !=
|
|
|
|
Context.getCanonicalType(New->getUnderlyingType())) {
|
2008-11-20 14:13:02 +08:00
|
|
|
Diag(New->getLocation(), diag::err_redefinition_different_typedef)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< New->getUnderlyingType() << Old->getUnderlyingType();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(Old->getLocation(), diag::note_previous_definition);
|
2008-07-26 02:44:27 +08:00
|
|
|
return Old;
|
|
|
|
}
|
|
|
|
|
2008-06-11 14:20:39 +08:00
|
|
|
if (getLangOptions().Microsoft) return New;
|
|
|
|
|
2008-11-22 00:29:06 +08:00
|
|
|
// C++ [dcl.typedef]p2:
|
|
|
|
// In a given non-class scope, a typedef specifier can be used to
|
|
|
|
// redefine the name of any type declared in that scope to refer
|
|
|
|
// to the type to which it already refers.
|
|
|
|
if (getLangOptions().CPlusPlus && !isa<CXXRecordDecl>(CurContext))
|
|
|
|
return New;
|
|
|
|
|
|
|
|
// In C, redeclaration of a type is a constraint violation (6.7.2.3p1).
|
2008-01-31 07:46:05 +08:00
|
|
|
// Apparently GCC, Intel, and Sun all silently ignore the redeclaration if
|
|
|
|
// *either* declaration is in a system header. The code below implements
|
|
|
|
// this adhoc compatibility rule. FIXME: The following code will not
|
|
|
|
// work properly when compiling ".i" files (containing preprocessed output).
|
2008-09-13 02:10:20 +08:00
|
|
|
if (PP.getDiagnostics().getSuppressSystemWarnings()) {
|
|
|
|
SourceManager &SrcMgr = Context.getSourceManager();
|
|
|
|
if (SrcMgr.isInSystemHeader(Old->getLocation()))
|
|
|
|
return New;
|
|
|
|
if (SrcMgr.isInSystemHeader(New->getLocation()))
|
|
|
|
return New;
|
|
|
|
}
|
2008-06-11 14:20:39 +08:00
|
|
|
|
2008-11-24 05:45:46 +08:00
|
|
|
Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(Old->getLocation(), diag::note_previous_definition);
|
2007-01-28 03:27:06 +08:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
2008-06-27 02:38:35 +08:00
|
|
|
/// DeclhasAttr - returns true if decl Declaration already has the target
|
|
|
|
/// attribute.
|
2008-03-03 11:28:21 +08:00
|
|
|
static bool DeclHasAttr(const Decl *decl, const Attr *target) {
|
|
|
|
for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext())
|
|
|
|
if (attr->getKind() == target->getKind())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// MergeAttributes - append attributes from the Old decl to the New one.
|
|
|
|
static void MergeAttributes(Decl *New, Decl *Old) {
|
|
|
|
Attr *attr = const_cast<Attr*>(Old->getAttrs()), *tmp;
|
|
|
|
|
|
|
|
while (attr) {
|
|
|
|
tmp = attr;
|
|
|
|
attr = attr->getNext();
|
|
|
|
|
|
|
|
if (!DeclHasAttr(New, tmp)) {
|
2008-12-26 08:52:02 +08:00
|
|
|
tmp->setInherited(true);
|
2008-03-03 11:28:21 +08:00
|
|
|
New->addAttr(tmp);
|
|
|
|
} else {
|
|
|
|
tmp->setNext(0);
|
|
|
|
delete(tmp);
|
|
|
|
}
|
|
|
|
}
|
2008-06-02 06:53:53 +08:00
|
|
|
|
|
|
|
Old->invalidateAttrs();
|
2008-03-03 11:28:21 +08:00
|
|
|
}
|
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
/// MergeFunctionDecl - We just parsed a function 'New' from
|
|
|
|
/// declarator D which has the same name and scope as a previous
|
|
|
|
/// declaration 'Old'. Figure out how to resolve this situation,
|
|
|
|
/// merging decls or emitting diagnostics as appropriate.
|
2008-10-22 00:13:35 +08:00
|
|
|
/// Redeclaration will be set true if this New is a redeclaration OldD.
|
|
|
|
///
|
|
|
|
/// In C++, New and Old must be declarations that are not
|
|
|
|
/// overloaded. Use IsOverload to determine whether New and Old are
|
|
|
|
/// overloaded, and to select the Old declaration that New should be
|
|
|
|
/// merged with.
|
2008-04-21 10:02:58 +08:00
|
|
|
FunctionDecl *
|
|
|
|
Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) {
|
2008-10-22 00:13:35 +08:00
|
|
|
assert(!isa<OverloadedFunctionDecl>(OldD) &&
|
|
|
|
"Cannot merge with an overloaded function declaration");
|
|
|
|
|
2008-04-21 10:02:58 +08:00
|
|
|
Redeclaration = false;
|
2007-01-28 03:32:14 +08:00
|
|
|
// Verify the old decl was also a function.
|
|
|
|
FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD);
|
|
|
|
if (!Old) {
|
2008-11-20 14:13:02 +08:00
|
|
|
Diag(New->getLocation(), diag::err_redefinition_different_kind)
|
2008-11-24 05:45:46 +08:00
|
|
|
<< New->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(OldD->getLocation(), diag::note_previous_definition);
|
2007-01-28 03:32:14 +08:00
|
|
|
return New;
|
|
|
|
}
|
2008-10-22 00:13:35 +08:00
|
|
|
|
|
|
|
// Determine whether the previous declaration was a definition,
|
|
|
|
// implicit declaration, or a declaration.
|
|
|
|
diag::kind PrevDiag;
|
|
|
|
if (Old->isThisDeclarationADefinition())
|
2008-11-24 07:12:31 +08:00
|
|
|
PrevDiag = diag::note_previous_definition;
|
2008-10-22 00:13:35 +08:00
|
|
|
else if (Old->isImplicit())
|
2008-11-24 07:12:31 +08:00
|
|
|
PrevDiag = diag::note_previous_implicit_declaration;
|
2008-10-22 00:13:35 +08:00
|
|
|
else
|
2008-11-24 07:12:31 +08:00
|
|
|
PrevDiag = diag::note_previous_declaration;
|
2008-04-08 12:40:51 +08:00
|
|
|
|
2008-04-07 07:10:54 +08:00
|
|
|
QualType OldQType = Context.getCanonicalType(Old->getType());
|
|
|
|
QualType NewQType = Context.getCanonicalType(New->getType());
|
2007-11-21 03:04:50 +08:00
|
|
|
|
2008-10-22 00:13:35 +08:00
|
|
|
if (getLangOptions().CPlusPlus) {
|
|
|
|
// (C++98 13.1p2):
|
|
|
|
// Certain function declarations cannot be overloaded:
|
|
|
|
// -- Function declarations that differ only in the return type
|
|
|
|
// cannot be overloaded.
|
|
|
|
QualType OldReturnType
|
|
|
|
= cast<FunctionType>(OldQType.getTypePtr())->getResultType();
|
|
|
|
QualType NewReturnType
|
|
|
|
= cast<FunctionType>(NewQType.getTypePtr())->getResultType();
|
|
|
|
if (OldReturnType != NewReturnType) {
|
|
|
|
Diag(New->getLocation(), diag::err_ovl_diff_return_type);
|
|
|
|
Diag(Old->getLocation(), PrevDiag);
|
2008-12-23 08:26:44 +08:00
|
|
|
Redeclaration = true;
|
2008-10-22 00:13:35 +08:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
|
|
|
|
const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
|
|
|
|
if (OldMethod && NewMethod) {
|
|
|
|
// -- Member function declarations with the same name and the
|
|
|
|
// same parameter types cannot be overloaded if any of them
|
|
|
|
// is a static member function declaration.
|
|
|
|
if (OldMethod->isStatic() || NewMethod->isStatic()) {
|
|
|
|
Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
|
|
|
|
Diag(Old->getLocation(), PrevDiag);
|
|
|
|
return New;
|
|
|
|
}
|
2008-12-16 05:24:18 +08:00
|
|
|
|
|
|
|
// C++ [class.mem]p1:
|
|
|
|
// [...] A member shall not be declared twice in the
|
|
|
|
// member-specification, except that a nested class or member
|
|
|
|
// class template can be declared and then later defined.
|
|
|
|
if (OldMethod->getLexicalDeclContext() ==
|
|
|
|
NewMethod->getLexicalDeclContext()) {
|
|
|
|
unsigned NewDiag;
|
|
|
|
if (isa<CXXConstructorDecl>(OldMethod))
|
|
|
|
NewDiag = diag::err_constructor_redeclared;
|
|
|
|
else if (isa<CXXDestructorDecl>(NewMethod))
|
|
|
|
NewDiag = diag::err_destructor_redeclared;
|
|
|
|
else if (isa<CXXConversionDecl>(NewMethod))
|
|
|
|
NewDiag = diag::err_conv_function_redeclared;
|
|
|
|
else
|
|
|
|
NewDiag = diag::err_member_redeclared;
|
|
|
|
|
|
|
|
Diag(New->getLocation(), NewDiag);
|
|
|
|
Diag(Old->getLocation(), PrevDiag);
|
|
|
|
}
|
2008-10-22 00:13:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// (C++98 8.3.5p3):
|
|
|
|
// All declarations for a function shall agree exactly in both the
|
|
|
|
// return type and the parameter-type-list.
|
|
|
|
if (OldQType == NewQType) {
|
|
|
|
// We have a redeclaration.
|
|
|
|
MergeAttributes(New, Old);
|
|
|
|
Redeclaration = true;
|
|
|
|
return MergeCXXFunctionDecl(New, Old);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall through for conflicting redeclarations and redefinitions.
|
2008-04-21 10:02:58 +08:00
|
|
|
}
|
2008-04-08 12:40:51 +08:00
|
|
|
|
|
|
|
// C: Function types need to be compatible, not identical. This handles
|
2008-01-15 04:51:29 +08:00
|
|
|
// duplicate function decls like "void f(int); void f(enum X);" properly.
|
2008-04-08 12:40:51 +08:00
|
|
|
if (!getLangOptions().CPlusPlus &&
|
2008-08-22 08:56:42 +08:00
|
|
|
Context.typesAreCompatible(OldQType, NewQType)) {
|
2008-04-21 10:02:58 +08:00
|
|
|
MergeAttributes(New, Old);
|
|
|
|
Redeclaration = true;
|
2008-01-15 04:51:29 +08:00
|
|
|
return New;
|
2008-04-08 12:40:51 +08:00
|
|
|
}
|
2007-11-06 14:07:26 +08:00
|
|
|
|
2008-01-16 23:01:34 +08:00
|
|
|
// A function that has already been declared has been redeclared or defined
|
|
|
|
// with a different type- show appropriate diagnostic
|
|
|
|
|
2007-01-28 03:27:06 +08:00
|
|
|
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
|
|
|
|
// TODO: This is totally simplistic. It should handle merging functions
|
|
|
|
// together etc, merging extern int X; int X; ...
|
2008-11-24 13:29:24 +08:00
|
|
|
Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName();
|
2008-01-16 23:01:34 +08:00
|
|
|
Diag(Old->getLocation(), PrevDiag);
|
2007-01-28 03:27:06 +08:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
2008-08-09 01:50:35 +08:00
|
|
|
/// Predicate for C "tentative" external object definitions (C99 6.9.2).
|
2008-08-10 23:28:06 +08:00
|
|
|
static bool isTentativeDefinition(VarDecl *VD) {
|
2008-08-09 01:50:35 +08:00
|
|
|
if (VD->isFileVarDecl())
|
|
|
|
return (!VD->getInit() &&
|
|
|
|
(VD->getStorageClass() == VarDecl::None ||
|
|
|
|
VD->getStorageClass() == VarDecl::Static));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// CheckForFileScopedRedefinitions - Make sure we forgo redefinition errors
|
|
|
|
/// when dealing with C "tentative" external object definitions (C99 6.9.2).
|
|
|
|
void Sema::CheckForFileScopedRedefinitions(Scope *S, VarDecl *VD) {
|
|
|
|
bool VDIsTentative = isTentativeDefinition(VD);
|
2008-08-10 23:20:13 +08:00
|
|
|
bool VDIsIncompleteArray = VD->getType()->isIncompleteArrayType();
|
2008-08-09 01:50:35 +08:00
|
|
|
|
2008-12-24 05:05:05 +08:00
|
|
|
// FIXME: I don't this will actually see all of the
|
|
|
|
// redefinitions. Can't we check this property on-the-fly?
|
2008-08-09 01:50:35 +08:00
|
|
|
for (IdentifierResolver::iterator
|
|
|
|
I = IdResolver.begin(VD->getIdentifier(),
|
|
|
|
VD->getDeclContext(), false/*LookInParentCtx*/),
|
|
|
|
E = IdResolver.end(); I != E; ++I) {
|
2008-09-10 05:18:04 +08:00
|
|
|
if (*I != VD && isDeclInScope(*I, VD->getDeclContext(), S)) {
|
2008-08-09 01:50:35 +08:00
|
|
|
VarDecl *OldDecl = dyn_cast<VarDecl>(*I);
|
|
|
|
|
2008-08-10 23:20:13 +08:00
|
|
|
// Handle the following case:
|
|
|
|
// int a[10];
|
|
|
|
// int a[]; - the code below makes sure we set the correct type.
|
|
|
|
// int a[11]; - this is an error, size isn't 10.
|
|
|
|
if (OldDecl && VDIsTentative && VDIsIncompleteArray &&
|
|
|
|
OldDecl->getType()->isConstantArrayType())
|
|
|
|
VD->setType(OldDecl->getType());
|
|
|
|
|
2008-08-09 01:50:35 +08:00
|
|
|
// Check for "tentative" definitions. We can't accomplish this in
|
|
|
|
// MergeVarDecl since the initializer hasn't been attached.
|
|
|
|
if (!OldDecl || isTentativeDefinition(OldDecl) || VDIsTentative)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Handle __private_extern__ just like extern.
|
|
|
|
if (OldDecl->getStorageClass() != VarDecl::Extern &&
|
|
|
|
OldDecl->getStorageClass() != VarDecl::PrivateExtern &&
|
|
|
|
VD->getStorageClass() != VarDecl::Extern &&
|
|
|
|
VD->getStorageClass() != VarDecl::PrivateExtern) {
|
2008-11-24 05:45:46 +08:00
|
|
|
Diag(VD->getLocation(), diag::err_redefinition) << VD->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(OldDecl->getLocation(), diag::note_previous_definition);
|
2008-08-09 01:50:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-01-28 03:27:06 +08:00
|
|
|
/// MergeVarDecl - We just parsed a variable 'New' which has the same name
|
|
|
|
/// and scope as a previous declaration 'Old'. Figure out how to resolve this
|
|
|
|
/// situation, merging decls or emitting diagnostics as appropriate.
|
|
|
|
///
|
2008-08-09 01:50:35 +08:00
|
|
|
/// Tentative definition rules (C99 6.9.2p2) are checked by
|
|
|
|
/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
|
|
|
|
/// definitions here, since the initializer hasn't been attached.
|
2007-04-02 05:27:45 +08:00
|
|
|
///
|
2008-04-02 07:04:06 +08:00
|
|
|
VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
|
2007-01-28 03:32:14 +08:00
|
|
|
// Verify the old decl was also a variable.
|
|
|
|
VarDecl *Old = dyn_cast<VarDecl>(OldD);
|
|
|
|
if (!Old) {
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(New->getLocation(), diag::err_redefinition_different_kind)
|
2008-11-24 05:45:46 +08:00
|
|
|
<< New->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(OldD->getLocation(), diag::note_previous_definition);
|
2007-01-28 03:32:14 +08:00
|
|
|
return New;
|
|
|
|
}
|
2008-03-03 11:28:21 +08:00
|
|
|
|
|
|
|
MergeAttributes(New, Old);
|
|
|
|
|
2008-01-30 08:44:01 +08:00
|
|
|
// Verify the types match.
|
2008-04-07 07:10:54 +08:00
|
|
|
QualType OldCType = Context.getCanonicalType(Old->getType());
|
|
|
|
QualType NewCType = Context.getCanonicalType(New->getType());
|
2008-08-10 00:04:40 +08:00
|
|
|
if (OldCType != NewCType && !Context.typesAreCompatible(OldCType, NewCType)) {
|
2008-11-24 05:45:46 +08:00
|
|
|
Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(Old->getLocation(), diag::note_previous_definition);
|
2008-01-30 08:44:01 +08:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
// C99 6.2.2p4: Check if we have a static decl followed by a non-static.
|
|
|
|
if (New->getStorageClass() == VarDecl::Static &&
|
|
|
|
(Old->getStorageClass() == VarDecl::None ||
|
|
|
|
Old->getStorageClass() == VarDecl::Extern)) {
|
2008-11-24 13:29:24 +08:00
|
|
|
Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(Old->getLocation(), diag::note_previous_definition);
|
2008-01-30 08:44:01 +08:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
// C99 6.2.2p4: Check if we have a non-static decl followed by a static.
|
|
|
|
if (New->getStorageClass() != VarDecl::Static &&
|
|
|
|
Old->getStorageClass() == VarDecl::Static) {
|
2008-11-24 13:29:24 +08:00
|
|
|
Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(Old->getLocation(), diag::note_previous_definition);
|
2008-01-30 08:44:01 +08:00
|
|
|
return New;
|
|
|
|
}
|
2008-09-17 22:05:40 +08:00
|
|
|
// Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
|
|
|
|
if (New->getStorageClass() != VarDecl::Extern && !New->isFileVarDecl()) {
|
2008-11-24 05:45:46 +08:00
|
|
|
Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(Old->getLocation(), diag::note_previous_definition);
|
2007-03-16 08:33:25 +08:00
|
|
|
}
|
2007-01-28 03:27:06 +08:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
/// CheckParmsForFunctionDef - Check that the parameters of the given
|
|
|
|
/// function are appropriate for the definition of a function. This
|
|
|
|
/// takes care of any checks that cannot be performed on the
|
|
|
|
/// declaration itself, e.g., that the types of each of the function
|
|
|
|
/// parameters are complete.
|
|
|
|
bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
|
|
|
|
bool HasInvalidParm = false;
|
|
|
|
for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
|
|
|
|
ParmVarDecl *Param = FD->getParamDecl(p);
|
|
|
|
|
|
|
|
// C99 6.7.5.3p4: the parameters in a parameter type list in a
|
|
|
|
// function declarator that is part of a function definition of
|
|
|
|
// that function shall not have incomplete type.
|
|
|
|
if (Param->getType()->isIncompleteType() &&
|
|
|
|
!Param->isInvalidDecl()) {
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(Param->getLocation(), diag::err_typecheck_decl_incomplete_type)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< Param->getType();
|
2008-04-08 12:40:51 +08:00
|
|
|
Param->setInvalidDecl();
|
|
|
|
HasInvalidParm = true;
|
|
|
|
}
|
2008-12-17 15:32:46 +08:00
|
|
|
|
|
|
|
// C99 6.9.1p5: If the declarator includes a parameter type list, the
|
|
|
|
// declaration of each parameter shall include an identifier.
|
|
|
|
if (Param->getIdentifier() == 0 && !getLangOptions().CPlusPlus)
|
|
|
|
Diag(Param->getLocation(), diag::err_parameter_name_omitted);
|
2008-04-08 12:40:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return HasInvalidParm;
|
|
|
|
}
|
|
|
|
|
2007-01-28 08:38:24 +08:00
|
|
|
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
|
|
|
|
/// no declarator (e.g. "struct foo;") is parsed.
|
|
|
|
Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
|
2008-12-28 23:28:59 +08:00
|
|
|
// FIXME: Isn't that more of a parser diagnostic than a sema diagnostic?
|
|
|
|
if (!DS.isMissingDeclaratorOk()) {
|
|
|
|
// FIXME: This diagnostic is emitted even when various previous
|
|
|
|
// errors occurred (see e.g. test/Sema/decl-invalid.c). However,
|
|
|
|
// DeclSpec has no means of communicating this information, and the
|
|
|
|
// responsible parser functions are quite far apart.
|
|
|
|
Diag(DS.getSourceRange().getBegin(), diag::err_no_declarators)
|
|
|
|
<< DS.getSourceRange();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-11-18 05:37:36 +08:00
|
|
|
return dyn_cast_or_null<TagDecl>(static_cast<Decl *>(DS.getTypeRep()));
|
2007-01-28 08:38:24 +08:00
|
|
|
}
|
|
|
|
|
2008-01-11 06:15:12 +08:00
|
|
|
bool Sema::CheckSingleInitializer(Expr *&Init, QualType DeclType) {
|
2007-09-02 10:04:30 +08:00
|
|
|
// Get the type before calling CheckSingleAssignmentConstraints(), since
|
|
|
|
// it can promote the expression.
|
2008-01-05 02:04:52 +08:00
|
|
|
QualType InitType = Init->getType();
|
2008-12-20 01:40:08 +08:00
|
|
|
|
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
return PerformCopyInitialization(Init, DeclType, "initializing");
|
|
|
|
|
2008-01-05 02:04:52 +08:00
|
|
|
AssignConvertType ConvTy = CheckSingleAssignmentConstraints(DeclType, Init);
|
|
|
|
return DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
|
|
|
|
InitType, Init, "initializing");
|
2007-09-02 10:04:30 +08:00
|
|
|
}
|
|
|
|
|
2008-01-22 08:55:40 +08:00
|
|
|
bool Sema::CheckStringLiteralInit(StringLiteral *strLiteral, QualType &DeclT) {
|
2008-08-04 15:31:14 +08:00
|
|
|
const ArrayType *AT = Context.getAsArrayType(DeclT);
|
|
|
|
|
|
|
|
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
|
2008-01-22 08:55:40 +08:00
|
|
|
// C99 6.7.8p14. We have an array of character type with unknown size
|
|
|
|
// being initialized to a string literal.
|
|
|
|
llvm::APSInt ConstVal(32);
|
|
|
|
ConstVal = strLiteral->getByteLength() + 1;
|
|
|
|
// Return a new array type (C99 6.7.8p22).
|
2008-02-16 02:16:39 +08:00
|
|
|
DeclT = Context.getConstantArrayType(IAT->getElementType(), ConstVal,
|
2008-01-22 08:55:40 +08:00
|
|
|
ArrayType::Normal, 0);
|
2008-08-04 15:31:14 +08:00
|
|
|
} else {
|
|
|
|
const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
|
2008-01-22 08:55:40 +08:00
|
|
|
// C99 6.7.8p14. We have an array of character type with known size.
|
2008-08-04 15:31:14 +08:00
|
|
|
// FIXME: Avoid truncation for 64-bit length strings.
|
|
|
|
if (strLiteral->getByteLength() > (unsigned)CAT->getSize().getZExtValue())
|
2008-01-22 08:55:40 +08:00
|
|
|
Diag(strLiteral->getSourceRange().getBegin(),
|
2008-11-19 13:27:50 +08:00
|
|
|
diag::warn_initializer_string_for_char_array_too_long)
|
|
|
|
<< strLiteral->getSourceRange();
|
2008-01-22 08:55:40 +08:00
|
|
|
}
|
|
|
|
// Set type from "char *" to "constant array of char".
|
|
|
|
strLiteral->setType(DeclT);
|
|
|
|
// For now, we always return false (meaning success).
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringLiteral *Sema::IsStringLiteralInit(Expr *Init, QualType DeclType) {
|
2008-08-04 15:31:14 +08:00
|
|
|
const ArrayType *AT = Context.getAsArrayType(DeclType);
|
2008-01-25 08:51:06 +08:00
|
|
|
if (AT && AT->getElementType()->isCharType()) {
|
|
|
|
return dyn_cast<StringLiteral>(Init);
|
|
|
|
}
|
2008-01-22 08:55:40 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-11-05 23:29:30 +08:00
|
|
|
bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
|
|
|
|
SourceLocation InitLoc,
|
2008-11-24 13:29:24 +08:00
|
|
|
DeclarationName InitEntity) {
|
2008-12-19 05:49:58 +08:00
|
|
|
if (DeclType->isDependentType() || Init->isTypeDependent())
|
|
|
|
return false;
|
|
|
|
|
2008-10-29 08:13:59 +08:00
|
|
|
// C++ [dcl.init.ref]p1:
|
2008-11-25 04:06:50 +08:00
|
|
|
// A variable declared to be a T&, that is "reference to type T"
|
2008-10-29 08:13:59 +08:00
|
|
|
// (8.3.2), shall be initialized by an object, or function, of
|
|
|
|
// type T or by an object that can be converted into a T.
|
|
|
|
if (DeclType->isReferenceType())
|
|
|
|
return CheckReferenceInit(Init, DeclType);
|
|
|
|
|
2008-01-22 07:53:58 +08:00
|
|
|
// C99 6.7.8p3: The type of the entity to be initialized shall be an array
|
|
|
|
// of unknown size ("[]") or an object type that is not a variable array type.
|
2008-08-04 15:31:14 +08:00
|
|
|
if (const VariableArrayType *VAT = Context.getAsVariableArrayType(DeclType))
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(InitLoc, diag::err_variable_object_no_init)
|
|
|
|
<< VAT->getSizeExpr()->getSourceRange();
|
2008-01-22 07:53:58 +08:00
|
|
|
|
2007-09-02 10:04:30 +08:00
|
|
|
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
|
2007-12-11 06:44:33 +08:00
|
|
|
if (!InitList) {
|
2008-01-22 08:55:40 +08:00
|
|
|
// FIXME: Handle wide strings
|
|
|
|
if (StringLiteral *strLiteral = IsStringLiteralInit(Init, DeclType))
|
|
|
|
return CheckStringLiteralInit(strLiteral, DeclType);
|
2008-02-08 08:48:24 +08:00
|
|
|
|
2008-11-05 23:29:30 +08:00
|
|
|
// C++ [dcl.init]p14:
|
|
|
|
// -- If the destination type is a (possibly cv-qualified) class
|
|
|
|
// type:
|
|
|
|
if (getLangOptions().CPlusPlus && DeclType->isRecordType()) {
|
|
|
|
QualType DeclTypeC = Context.getCanonicalType(DeclType);
|
|
|
|
QualType InitTypeC = Context.getCanonicalType(Init->getType());
|
|
|
|
|
|
|
|
// -- If the initialization is direct-initialization, or if it is
|
|
|
|
// copy-initialization where the cv-unqualified version of the
|
|
|
|
// source type is the same class as, or a derived class of, the
|
|
|
|
// class of the destination, constructors are considered.
|
|
|
|
if ((DeclTypeC.getUnqualifiedType() == InitTypeC.getUnqualifiedType()) ||
|
|
|
|
IsDerivedFrom(InitTypeC, DeclTypeC)) {
|
|
|
|
CXXConstructorDecl *Constructor
|
|
|
|
= PerformInitializationByConstructor(DeclType, &Init, 1,
|
|
|
|
InitLoc, Init->getSourceRange(),
|
|
|
|
InitEntity, IK_Copy);
|
|
|
|
return Constructor == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -- Otherwise (i.e., for the remaining copy-initialization
|
|
|
|
// cases), user-defined conversion sequences that can
|
|
|
|
// convert from the source type to the destination type or
|
|
|
|
// (when a conversion function is used) to a derived class
|
|
|
|
// thereof are enumerated as described in 13.3.1.4, and the
|
|
|
|
// best one is chosen through overload resolution
|
|
|
|
// (13.3). If the conversion cannot be done or is
|
|
|
|
// ambiguous, the initialization is ill-formed. The
|
|
|
|
// function selected is called with the initializer
|
|
|
|
// expression as its argument; if the function is a
|
|
|
|
// constructor, the call initializes a temporary of the
|
|
|
|
// destination type.
|
|
|
|
// FIXME: We're pretending to do copy elision here; return to
|
|
|
|
// this when we have ASTs for such things.
|
2008-12-20 01:40:08 +08:00
|
|
|
if (!PerformImplicitConversion(Init, DeclType, "initializing"))
|
2008-11-05 23:29:30 +08:00
|
|
|
return false;
|
2008-11-19 06:52:51 +08:00
|
|
|
|
2008-12-24 08:01:03 +08:00
|
|
|
if (InitEntity)
|
|
|
|
return Diag(InitLoc, diag::err_cannot_initialize_decl)
|
|
|
|
<< InitEntity << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
|
|
|
|
<< Init->getType() << Init->getSourceRange();
|
|
|
|
else
|
|
|
|
return Diag(InitLoc, diag::err_cannot_initialize_decl_noname)
|
|
|
|
<< DeclType << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
|
|
|
|
<< Init->getType() << Init->getSourceRange();
|
2008-11-05 23:29:30 +08:00
|
|
|
}
|
|
|
|
|
2008-09-30 04:07:05 +08:00
|
|
|
// C99 6.7.8p16.
|
2008-02-08 08:48:24 +08:00
|
|
|
if (DeclType->isArrayType())
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(Init->getLocStart(), diag::err_array_init_list_required)
|
|
|
|
<< Init->getSourceRange();
|
2008-02-08 08:48:24 +08:00
|
|
|
|
2008-01-11 06:15:12 +08:00
|
|
|
return CheckSingleInitializer(Init, DeclType);
|
2008-11-06 00:20:31 +08:00
|
|
|
} else if (getLangOptions().CPlusPlus) {
|
|
|
|
// C++ [dcl.init]p14:
|
|
|
|
// [...] If the class is an aggregate (8.5.1), and the initializer
|
|
|
|
// is a brace-enclosed list, see 8.5.1.
|
|
|
|
//
|
|
|
|
// Note: 8.5.1 is handled below; here, we diagnose the case where
|
|
|
|
// we have an initializer list and a destination type that is not
|
|
|
|
// an aggregate.
|
|
|
|
// FIXME: In C++0x, this is yet another form of initialization.
|
|
|
|
if (const RecordType *ClassRec = DeclType->getAsRecordType()) {
|
|
|
|
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
|
|
|
|
if (!ClassDecl->isAggregate())
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(InitLoc, diag::err_init_non_aggr_init_list)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< DeclType << Init->getSourceRange();
|
2008-11-06 00:20:31 +08:00
|
|
|
}
|
2007-12-11 06:44:33 +08:00
|
|
|
}
|
2008-06-07 03:40:52 +08:00
|
|
|
|
2008-05-02 06:18:59 +08:00
|
|
|
InitListChecker CheckInitList(this, InitList, DeclType);
|
|
|
|
return CheckInitList.HadError();
|
2007-09-02 10:04:30 +08:00
|
|
|
}
|
|
|
|
|
2008-11-18 06:58:34 +08:00
|
|
|
/// GetNameForDeclarator - Determine the full declaration name for the
|
|
|
|
/// given Declarator.
|
|
|
|
DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
|
|
|
|
switch (D.getKind()) {
|
|
|
|
case Declarator::DK_Abstract:
|
|
|
|
assert(D.getIdentifier() == 0 && "abstract declarators have no name");
|
|
|
|
return DeclarationName();
|
|
|
|
|
|
|
|
case Declarator::DK_Normal:
|
|
|
|
assert (D.getIdentifier() != 0 && "normal declarators have an identifier");
|
|
|
|
return DeclarationName(D.getIdentifier());
|
|
|
|
|
|
|
|
case Declarator::DK_Constructor: {
|
|
|
|
QualType Ty = Context.getTypeDeclType((TypeDecl *)D.getDeclaratorIdType());
|
|
|
|
Ty = Context.getCanonicalType(Ty);
|
|
|
|
return Context.DeclarationNames.getCXXConstructorName(Ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Declarator::DK_Destructor: {
|
|
|
|
QualType Ty = Context.getTypeDeclType((TypeDecl *)D.getDeclaratorIdType());
|
|
|
|
Ty = Context.getCanonicalType(Ty);
|
|
|
|
return Context.DeclarationNames.getCXXDestructorName(Ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Declarator::DK_Conversion: {
|
|
|
|
QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
|
|
|
|
Ty = Context.getCanonicalType(Ty);
|
|
|
|
return Context.DeclarationNames.getCXXConversionFunctionName(Ty);
|
|
|
|
}
|
Extend DeclarationName to support C++ overloaded operators, e.g.,
operator+, directly, using the same mechanism as all other special
names.
Removed the "special" identifiers for the overloaded operators from
the identifier table and IdentifierInfo data structure. IdentifierInfo
is back to representing only real identifiers.
Added a new Action, ActOnOperatorFunctionIdExpr, that builds an
expression from an parsed operator-function-id (e.g., "operator
+"). ActOnIdentifierExpr used to do this job, but
operator-function-ids are no longer represented by IdentifierInfo's.
Extended Declarator to store overloaded operator names.
Sema::GetNameForDeclarator now knows how to turn the operator
name into a DeclarationName for the overloaded operator.
Except for (perhaps) consolidating the functionality of
ActOnIdentifier, ActOnOperatorFunctionIdExpr, and
ActOnConversionFunctionExpr into a common routine that builds an
appropriate DeclRefExpr by looking up a DeclarationName, all of the
work on normalizing declaration names should be complete with this
commit.
llvm-svn: 59526
2008-11-18 22:39:36 +08:00
|
|
|
|
|
|
|
case Declarator::DK_Operator:
|
|
|
|
assert(D.getIdentifier() == 0 && "operator names have no identifier");
|
|
|
|
return Context.DeclarationNames.getCXXOperatorName(
|
|
|
|
D.getOverloadedOperator());
|
2008-11-18 06:58:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(false && "Unknown name kind");
|
|
|
|
return DeclarationName();
|
|
|
|
}
|
|
|
|
|
2008-12-16 07:53:10 +08:00
|
|
|
/// isNearlyMatchingMemberFunction - Determine whether the C++ member
|
|
|
|
/// functions Declaration and Definition are "nearly" matching. This
|
|
|
|
/// heuristic is used to improve diagnostics in the case where an
|
|
|
|
/// out-of-line member function definition doesn't match any
|
|
|
|
/// declaration within the class.
|
|
|
|
static bool isNearlyMatchingMemberFunction(ASTContext &Context,
|
|
|
|
FunctionDecl *Declaration,
|
|
|
|
FunctionDecl *Definition) {
|
|
|
|
if (Declaration->param_size() != Definition->param_size())
|
|
|
|
return false;
|
|
|
|
for (unsigned Idx = 0; Idx < Declaration->param_size(); ++Idx) {
|
|
|
|
QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType();
|
|
|
|
QualType DefParamTy = Definition->getParamDecl(Idx)->getType();
|
|
|
|
|
|
|
|
DeclParamTy = Context.getCanonicalType(DeclParamTy.getNonReferenceType());
|
|
|
|
DefParamTy = Context.getCanonicalType(DefParamTy.getNonReferenceType());
|
|
|
|
if (DeclParamTy.getUnqualifiedType() != DefParamTy.getUnqualifiedType())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-06-09 08:53:06 +08:00
|
|
|
Sema::DeclTy *
|
2008-12-16 07:53:10 +08:00
|
|
|
Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
|
|
|
|
bool IsFunctionDefinition) {
|
2007-09-14 07:52:58 +08:00
|
|
|
ScopedDecl *LastDeclarator = dyn_cast_or_null<ScopedDecl>((Decl *)lastDecl);
|
2008-11-18 06:58:34 +08:00
|
|
|
DeclarationName Name = GetNameForDeclarator(D);
|
|
|
|
|
2007-07-25 08:24:17 +08:00
|
|
|
// All of these full declarators require an identifier. If it doesn't have
|
|
|
|
// one, the ParsedFreeStandingDeclSpec action should be used.
|
2008-11-18 06:58:34 +08:00
|
|
|
if (!Name) {
|
2008-11-11 14:13:16 +08:00
|
|
|
if (!D.getInvalidType()) // Reject this if we think it is valid.
|
|
|
|
Diag(D.getDeclSpec().getSourceRange().getBegin(),
|
2008-11-19 13:08:23 +08:00
|
|
|
diag::err_declarator_need_ident)
|
|
|
|
<< D.getDeclSpec().getSourceRange() << D.getSourceRange();
|
2007-07-25 08:24:17 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-08-26 14:24:45 +08:00
|
|
|
// The scope passed in may not be a decl scope. Zip up the scope tree until
|
|
|
|
// we find one that is.
|
2008-12-12 00:49:14 +08:00
|
|
|
while ((S->getFlags() & Scope::DeclScope) == 0 ||
|
|
|
|
(S->getFlags() & Scope::TemplateParamScope) != 0)
|
2007-08-26 14:24:45 +08:00
|
|
|
S = S->getParent();
|
|
|
|
|
2008-11-09 01:17:31 +08:00
|
|
|
DeclContext *DC;
|
|
|
|
Decl *PrevDecl;
|
2007-09-14 02:10:37 +08:00
|
|
|
ScopedDecl *New;
|
2007-08-29 04:14:24 +08:00
|
|
|
bool InvalidDecl = false;
|
2008-04-14 05:07:44 +08:00
|
|
|
|
2008-11-09 01:17:31 +08:00
|
|
|
// See if this is a redefinition of a variable in the same scope.
|
|
|
|
if (!D.getCXXScopeSpec().isSet()) {
|
|
|
|
DC = CurContext;
|
2008-11-18 06:58:34 +08:00
|
|
|
PrevDecl = LookupDecl(Name, Decl::IDNS_Ordinary, S);
|
2008-11-09 01:17:31 +08:00
|
|
|
} else { // Something like "int foo::x;"
|
|
|
|
DC = static_cast<DeclContext*>(D.getCXXScopeSpec().getScopeRep());
|
2008-11-18 06:58:34 +08:00
|
|
|
PrevDecl = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC);
|
2008-11-09 01:17:31 +08:00
|
|
|
|
|
|
|
// C++ 7.3.1.2p2:
|
|
|
|
// Members (including explicit specializations of templates) of a named
|
|
|
|
// namespace can also be defined outside that namespace by explicit
|
|
|
|
// qualification of the name being defined, provided that the entity being
|
|
|
|
// defined was already declared in the namespace and the definition appears
|
|
|
|
// after the point of declaration in a namespace that encloses the
|
|
|
|
// declarations namespace.
|
|
|
|
//
|
2008-12-16 07:53:10 +08:00
|
|
|
// Note that we only check the context at this point. We don't yet
|
|
|
|
// have enough information to make sure that PrevDecl is actually
|
|
|
|
// the declaration we want to match. For example, given:
|
|
|
|
//
|
2008-12-12 16:25:50 +08:00
|
|
|
// class X {
|
|
|
|
// void f();
|
2008-12-16 07:53:10 +08:00
|
|
|
// void f(float);
|
2008-12-12 16:25:50 +08:00
|
|
|
// };
|
|
|
|
//
|
2008-12-16 07:53:10 +08:00
|
|
|
// void X::f(int) { } // ill-formed
|
|
|
|
//
|
|
|
|
// In this case, PrevDecl will point to the overload set
|
|
|
|
// containing the two f's declared in X, but neither of them
|
|
|
|
// matches.
|
|
|
|
if (!CurContext->Encloses(DC)) {
|
2008-11-09 01:17:31 +08:00
|
|
|
// The qualifying scope doesn't enclose the original declaration.
|
|
|
|
// Emit diagnostic based on current scope.
|
|
|
|
SourceLocation L = D.getIdentifierLoc();
|
|
|
|
SourceRange R = D.getCXXScopeSpec().getRange();
|
|
|
|
if (isa<FunctionDecl>(CurContext)) {
|
2008-11-24 04:28:15 +08:00
|
|
|
Diag(L, diag::err_invalid_declarator_in_function) << Name << R;
|
2008-11-09 01:17:31 +08:00
|
|
|
} else {
|
2008-11-24 04:28:15 +08:00
|
|
|
Diag(L, diag::err_invalid_declarator_scope)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< Name << cast<NamedDecl>(DC)->getDeclName() << R;
|
2008-11-09 01:17:31 +08:00
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
InvalidDecl = true;
|
2008-11-09 01:17:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-09 02:40:42 +08:00
|
|
|
if (PrevDecl && PrevDecl->isTemplateParameter()) {
|
2008-12-06 02:15:24 +08:00
|
|
|
// Maybe we will complain about the shadowed template parameter.
|
2008-12-06 07:32:09 +08:00
|
|
|
InvalidDecl = InvalidDecl
|
|
|
|
|| DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
|
2008-12-06 02:15:24 +08:00
|
|
|
// Just pretend that we didn't see the previous declaration.
|
|
|
|
PrevDecl = 0;
|
|
|
|
}
|
|
|
|
|
2008-04-14 05:07:44 +08:00
|
|
|
// In C++, the previous declaration we find might be a tag type
|
|
|
|
// (class or enum). In this case, the new declaration will hide the
|
|
|
|
// tag type.
|
|
|
|
if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
|
|
|
|
PrevDecl = 0;
|
|
|
|
|
2007-11-14 14:34:38 +08:00
|
|
|
QualType R = GetTypeForDeclarator(D, S);
|
|
|
|
assert(!R.isNull() && "GetTypeForDeclarator() returned null type");
|
|
|
|
|
2007-01-26 07:09:03 +08:00
|
|
|
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
|
2008-12-16 07:53:10 +08:00
|
|
|
// Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
|
|
|
|
if (D.getCXXScopeSpec().isSet()) {
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
|
|
|
|
<< D.getCXXScopeSpec().getRange();
|
|
|
|
InvalidDecl = true;
|
|
|
|
// Pretend we didn't see the scope specifier.
|
|
|
|
DC = 0;
|
|
|
|
}
|
|
|
|
|
2008-05-07 12:49:29 +08:00
|
|
|
// Check that there are no default arguments (C++ only).
|
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
CheckExtraCXXDefaultArguments(D);
|
|
|
|
|
2007-11-14 14:34:38 +08:00
|
|
|
TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, LastDeclarator);
|
2007-01-28 03:27:06 +08:00
|
|
|
if (!NewTD) return 0;
|
2007-06-11 08:35:03 +08:00
|
|
|
|
|
|
|
// Handle attributes prior to checking for duplicates in MergeVarDecl
|
2008-06-29 08:02:00 +08:00
|
|
|
ProcessDeclAttributes(NewTD, D);
|
2008-01-10 07:34:55 +08:00
|
|
|
// Merge the decl with the existing one if appropriate. If the decl is
|
|
|
|
// in an outer scope, it isn't the same thing.
|
2008-11-09 01:17:31 +08:00
|
|
|
if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
|
2007-01-28 03:27:06 +08:00
|
|
|
NewTD = MergeTypeDefDecl(NewTD, PrevDecl);
|
|
|
|
if (NewTD == 0) return 0;
|
|
|
|
}
|
|
|
|
New = NewTD;
|
2008-05-10 07:39:43 +08:00
|
|
|
if (S->getFnParent() == 0) {
|
2007-05-09 05:09:37 +08:00
|
|
|
// C99 6.7.7p2: If a typedef name specifies a variably modified type
|
|
|
|
// then it shall have block scope.
|
2008-02-15 20:53:51 +08:00
|
|
|
if (NewTD->getUnderlyingType()->isVariablyModifiedType()) {
|
2008-12-07 08:20:55 +08:00
|
|
|
if (NewTD->getUnderlyingType()->isVariableArrayType())
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope);
|
|
|
|
else
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope);
|
|
|
|
|
2007-09-01 01:20:07 +08:00
|
|
|
InvalidDecl = true;
|
2007-05-09 05:09:37 +08:00
|
|
|
}
|
|
|
|
}
|
2007-11-14 14:34:38 +08:00
|
|
|
} else if (R.getTypePtr()->isFunctionType()) {
|
2007-09-27 23:15:46 +08:00
|
|
|
FunctionDecl::StorageClass SC = FunctionDecl::None;
|
2007-04-04 07:13:13 +08:00
|
|
|
switch (D.getDeclSpec().getStorageClassSpec()) {
|
|
|
|
default: assert(0 && "Unknown storage class!");
|
|
|
|
case DeclSpec::SCS_auto:
|
|
|
|
case DeclSpec::SCS_register:
|
2008-11-15 07:42:31 +08:00
|
|
|
case DeclSpec::SCS_mutable:
|
2008-11-24 14:25:27 +08:00
|
|
|
Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_func);
|
2007-08-29 04:14:24 +08:00
|
|
|
InvalidDecl = true;
|
|
|
|
break;
|
2007-04-04 07:13:13 +08:00
|
|
|
case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break;
|
|
|
|
case DeclSpec::SCS_extern: SC = FunctionDecl::Extern; break;
|
|
|
|
case DeclSpec::SCS_static: SC = FunctionDecl::Static; break;
|
2008-01-29 05:57:15 +08:00
|
|
|
case DeclSpec::SCS_private_extern: SC = FunctionDecl::PrivateExtern;break;
|
2007-04-04 07:13:13 +08:00
|
|
|
}
|
|
|
|
|
2008-03-16 05:24:04 +08:00
|
|
|
bool isInline = D.getDeclSpec().isInlineSpecified();
|
2008-11-06 04:51:48 +08:00
|
|
|
// bool isVirtual = D.getDeclSpec().isVirtualSpecified();
|
2008-10-31 17:07:45 +08:00
|
|
|
bool isExplicit = D.getDeclSpec().isExplicitSpecified();
|
|
|
|
|
2008-07-01 18:37:29 +08:00
|
|
|
FunctionDecl *NewFD;
|
2008-11-06 04:51:48 +08:00
|
|
|
if (D.getKind() == Declarator::DK_Constructor) {
|
2008-10-31 17:07:45 +08:00
|
|
|
// This is a C++ constructor declaration.
|
2008-11-09 01:17:31 +08:00
|
|
|
assert(DC->isCXXRecord() &&
|
2008-10-31 17:07:45 +08:00
|
|
|
"Constructors can only be declared in a member context");
|
|
|
|
|
2008-12-24 05:05:05 +08:00
|
|
|
InvalidDecl = InvalidDecl || CheckConstructorDeclarator(D, R, SC);
|
2008-10-31 17:07:45 +08:00
|
|
|
|
|
|
|
// Create the new declaration
|
|
|
|
NewFD = CXXConstructorDecl::Create(Context,
|
2008-11-09 01:17:31 +08:00
|
|
|
cast<CXXRecordDecl>(DC),
|
2008-11-18 06:58:34 +08:00
|
|
|
D.getIdentifierLoc(), Name, R,
|
2008-10-31 17:07:45 +08:00
|
|
|
isExplicit, isInline,
|
|
|
|
/*isImplicitlyDeclared=*/false);
|
|
|
|
|
2008-12-24 05:05:05 +08:00
|
|
|
if (InvalidDecl)
|
2008-11-06 04:51:48 +08:00
|
|
|
NewFD->setInvalidDecl();
|
|
|
|
} else if (D.getKind() == Declarator::DK_Destructor) {
|
|
|
|
// This is a C++ destructor declaration.
|
2008-11-09 01:17:31 +08:00
|
|
|
if (DC->isCXXRecord()) {
|
2008-12-24 05:05:05 +08:00
|
|
|
InvalidDecl = InvalidDecl || CheckDestructorDeclarator(D, R, SC);
|
2008-11-06 04:51:48 +08:00
|
|
|
|
2008-11-08 06:02:30 +08:00
|
|
|
NewFD = CXXDestructorDecl::Create(Context,
|
2008-11-09 01:17:31 +08:00
|
|
|
cast<CXXRecordDecl>(DC),
|
2008-11-18 06:58:34 +08:00
|
|
|
D.getIdentifierLoc(), Name, R,
|
2008-11-08 06:02:30 +08:00
|
|
|
isInline,
|
|
|
|
/*isImplicitlyDeclared=*/false);
|
2008-11-06 04:51:48 +08:00
|
|
|
|
2008-12-24 05:05:05 +08:00
|
|
|
if (InvalidDecl)
|
2008-11-08 06:02:30 +08:00
|
|
|
NewFD->setInvalidDecl();
|
|
|
|
} else {
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
|
2008-12-24 05:05:05 +08:00
|
|
|
|
2008-11-08 06:02:30 +08:00
|
|
|
// Create a FunctionDecl to satisfy the function definition parsing
|
|
|
|
// code path.
|
2008-11-09 01:17:31 +08:00
|
|
|
NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
|
2008-11-18 06:58:34 +08:00
|
|
|
Name, R, SC, isInline, LastDeclarator,
|
2008-11-08 06:02:30 +08:00
|
|
|
// FIXME: Move to DeclGroup...
|
|
|
|
D.getDeclSpec().getSourceRange().getBegin());
|
2008-12-24 05:05:05 +08:00
|
|
|
InvalidDecl = true;
|
2008-11-06 04:51:48 +08:00
|
|
|
NewFD->setInvalidDecl();
|
2008-11-08 06:02:30 +08:00
|
|
|
}
|
2008-11-08 04:08:42 +08:00
|
|
|
} else if (D.getKind() == Declarator::DK_Conversion) {
|
2008-11-09 01:17:31 +08:00
|
|
|
if (!DC->isCXXRecord()) {
|
2008-11-08 04:08:42 +08:00
|
|
|
Diag(D.getIdentifierLoc(),
|
|
|
|
diag::err_conv_function_not_member);
|
|
|
|
return 0;
|
|
|
|
} else {
|
2008-12-24 05:05:05 +08:00
|
|
|
InvalidDecl = InvalidDecl || CheckConversionDeclarator(D, R, SC);
|
2008-11-08 04:08:42 +08:00
|
|
|
|
2008-12-26 23:00:45 +08:00
|
|
|
NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
|
2008-11-18 06:58:34 +08:00
|
|
|
D.getIdentifierLoc(), Name, R,
|
2008-11-08 04:08:42 +08:00
|
|
|
isInline, isExplicit);
|
|
|
|
|
2008-12-24 05:05:05 +08:00
|
|
|
if (InvalidDecl)
|
2008-11-08 04:08:42 +08:00
|
|
|
NewFD->setInvalidDecl();
|
|
|
|
}
|
2008-11-09 01:17:31 +08:00
|
|
|
} else if (DC->isCXXRecord()) {
|
2008-07-01 18:37:29 +08:00
|
|
|
// This is a C++ method declaration.
|
2008-11-09 01:17:31 +08:00
|
|
|
NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
|
2008-11-18 06:58:34 +08:00
|
|
|
D.getIdentifierLoc(), Name, R,
|
2008-07-01 18:37:29 +08:00
|
|
|
(SC == FunctionDecl::Static), isInline,
|
|
|
|
LastDeclarator);
|
|
|
|
} else {
|
2008-11-09 01:17:31 +08:00
|
|
|
NewFD = FunctionDecl::Create(Context, DC,
|
2008-07-01 18:37:29 +08:00
|
|
|
D.getIdentifierLoc(),
|
2008-11-18 06:58:34 +08:00
|
|
|
Name, R, SC, isInline, LastDeclarator,
|
2008-10-03 08:02:03 +08:00
|
|
|
// FIXME: Move to DeclGroup...
|
|
|
|
D.getDeclSpec().getSourceRange().getBegin());
|
2008-07-01 18:37:29 +08:00
|
|
|
}
|
2008-12-16 07:53:10 +08:00
|
|
|
|
2008-12-16 05:24:18 +08:00
|
|
|
// Set the lexical context. If the declarator has a C++
|
|
|
|
// scope specifier, the lexical context will be different
|
|
|
|
// from the semantic context.
|
|
|
|
NewFD->setLexicalDeclContext(CurContext);
|
|
|
|
|
2008-08-05 09:35:17 +08:00
|
|
|
// Handle GNU asm-label extension (encoded as an attribute).
|
2008-08-06 00:28:08 +08:00
|
|
|
if (Expr *E = (Expr*) D.getAsmLabel()) {
|
2008-08-05 09:35:17 +08:00
|
|
|
// The parser guarantees this is a string.
|
|
|
|
StringLiteral *SE = cast<StringLiteral>(E);
|
|
|
|
NewFD->addAttr(new AsmLabelAttr(std::string(SE->getStrData(),
|
|
|
|
SE->getByteLength())));
|
|
|
|
}
|
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
// Copy the parameter declarations from the declarator D to
|
|
|
|
// the function declaration NewFD, if they are available.
|
2008-08-26 05:31:01 +08:00
|
|
|
if (D.getNumTypeObjects() > 0) {
|
2008-04-08 12:40:51 +08:00
|
|
|
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
|
|
|
|
|
|
|
|
// Create Decl objects for each parameter, adding them to the
|
|
|
|
// FunctionDecl.
|
|
|
|
llvm::SmallVector<ParmVarDecl*, 16> Params;
|
|
|
|
|
|
|
|
// Check for C99 6.7.5.3p10 - foo(void) is a non-varargs
|
|
|
|
// function that takes no arguments, not a function that takes a
|
2008-04-10 10:22:51 +08:00
|
|
|
// single void argument.
|
2008-05-22 16:54:03 +08:00
|
|
|
// We let through "const void" here because Sema::GetTypeForDeclarator
|
|
|
|
// already checks for that case.
|
2008-04-08 12:40:51 +08:00
|
|
|
if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
|
|
|
|
FTI.ArgInfo[0].Param &&
|
|
|
|
((ParmVarDecl*)FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
|
|
|
|
// empty arg list, don't push any params.
|
2008-04-10 10:22:51 +08:00
|
|
|
ParmVarDecl *Param = (ParmVarDecl*)FTI.ArgInfo[0].Param;
|
|
|
|
|
2008-04-10 10:26:16 +08:00
|
|
|
// In C++, the empty parameter-type-list must be spelled "void"; a
|
|
|
|
// typedef of void is not permitted.
|
|
|
|
if (getLangOptions().CPlusPlus &&
|
2008-05-22 16:54:03 +08:00
|
|
|
Param->getType().getUnqualifiedType() != Context.VoidTy) {
|
2008-04-10 10:22:51 +08:00
|
|
|
Diag(Param->getLocation(), diag::ext_param_typedef_of_void);
|
|
|
|
}
|
2008-08-26 05:31:01 +08:00
|
|
|
} else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
|
2008-04-08 12:40:51 +08:00
|
|
|
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
|
|
|
|
Params.push_back((ParmVarDecl *)FTI.ArgInfo[i].Param);
|
|
|
|
}
|
|
|
|
|
|
|
|
NewFD->setParams(&Params[0], Params.size());
|
2008-10-25 02:09:54 +08:00
|
|
|
} else if (R->getAsTypedefType()) {
|
|
|
|
// When we're declaring a function with a typedef, as in the
|
|
|
|
// following example, we'll need to synthesize (unnamed)
|
|
|
|
// parameters for use in the declaration.
|
|
|
|
//
|
|
|
|
// @code
|
|
|
|
// typedef void fn(int);
|
|
|
|
// fn f;
|
|
|
|
// @endcode
|
|
|
|
const FunctionTypeProto *FT = R->getAsFunctionTypeProto();
|
|
|
|
if (!FT) {
|
|
|
|
// This is a typedef of a function with no prototype, so we
|
|
|
|
// don't need to do anything.
|
|
|
|
} else if ((FT->getNumArgs() == 0) ||
|
|
|
|
(FT->getNumArgs() == 1 && !FT->isVariadic() &&
|
|
|
|
FT->getArgType(0)->isVoidType())) {
|
|
|
|
// This is a zero-argument function. We don't need to do anything.
|
|
|
|
} else {
|
|
|
|
// Synthesize a parameter for each argument type.
|
|
|
|
llvm::SmallVector<ParmVarDecl*, 16> Params;
|
|
|
|
for (FunctionTypeProto::arg_type_iterator ArgType = FT->arg_type_begin();
|
|
|
|
ArgType != FT->arg_type_end(); ++ArgType) {
|
2008-11-09 01:17:31 +08:00
|
|
|
Params.push_back(ParmVarDecl::Create(Context, DC,
|
2008-10-25 02:09:54 +08:00
|
|
|
SourceLocation(), 0,
|
|
|
|
*ArgType, VarDecl::None,
|
|
|
|
0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
NewFD->setParams(&Params[0], Params.size());
|
|
|
|
}
|
2008-04-08 12:40:51 +08:00
|
|
|
}
|
|
|
|
|
2008-12-17 05:30:33 +08:00
|
|
|
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD))
|
|
|
|
InvalidDecl = InvalidDecl || CheckConstructor(Constructor);
|
2008-12-16 05:24:18 +08:00
|
|
|
else if (isa<CXXDestructorDecl>(NewFD))
|
|
|
|
cast<CXXRecordDecl>(NewFD->getParent())->setUserDeclaredDestructor(true);
|
|
|
|
else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
|
2008-11-18 04:34:05 +08:00
|
|
|
ActOnConversionDeclarator(Conversion);
|
2008-10-31 17:07:45 +08:00
|
|
|
|
2008-11-07 06:13:31 +08:00
|
|
|
// Extra checking for C++ overloaded operators (C++ [over.oper]).
|
|
|
|
if (NewFD->isOverloadedOperator() &&
|
|
|
|
CheckOverloadedOperatorDeclaration(NewFD))
|
|
|
|
NewFD->setInvalidDecl();
|
|
|
|
|
2008-01-10 07:34:55 +08:00
|
|
|
// Merge the decl with the existing one if appropriate. Since C functions
|
|
|
|
// are in a flat namespace, make sure we consider decls in outer scopes.
|
2008-05-10 07:39:43 +08:00
|
|
|
if (PrevDecl &&
|
2008-11-09 01:17:31 +08:00
|
|
|
(!getLangOptions().CPlusPlus||isDeclInScope(PrevDecl, DC, S))) {
|
2008-04-21 10:02:58 +08:00
|
|
|
bool Redeclaration = false;
|
2008-10-22 00:13:35 +08:00
|
|
|
|
|
|
|
// If C++, determine whether NewFD is an overload of PrevDecl or
|
|
|
|
// a declaration that requires merging. If it's an overload,
|
|
|
|
// there's no more work to do here; we'll just add the new
|
|
|
|
// function to the scope.
|
|
|
|
OverloadedFunctionDecl::function_iterator MatchedDecl;
|
|
|
|
if (!getLangOptions().CPlusPlus ||
|
|
|
|
!IsOverload(NewFD, PrevDecl, MatchedDecl)) {
|
|
|
|
Decl *OldDecl = PrevDecl;
|
|
|
|
|
|
|
|
// If PrevDecl was an overloaded function, extract the
|
|
|
|
// FunctionDecl that matched.
|
|
|
|
if (isa<OverloadedFunctionDecl>(PrevDecl))
|
|
|
|
OldDecl = *MatchedDecl;
|
|
|
|
|
|
|
|
// NewFD and PrevDecl represent declarations that need to be
|
|
|
|
// merged.
|
|
|
|
NewFD = MergeFunctionDecl(NewFD, OldDecl, Redeclaration);
|
|
|
|
|
|
|
|
if (NewFD == 0) return 0;
|
|
|
|
if (Redeclaration) {
|
|
|
|
NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
|
|
|
|
|
2008-12-24 05:05:05 +08:00
|
|
|
// An out-of-line member function declaration must also be a
|
|
|
|
// definition (C++ [dcl.meaning]p1).
|
|
|
|
if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() &&
|
|
|
|
!InvalidDecl) {
|
|
|
|
Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
|
|
|
|
<< D.getCXXScopeSpec().getRange();
|
|
|
|
NewFD->setInvalidDecl();
|
2008-10-22 00:13:35 +08:00
|
|
|
}
|
|
|
|
}
|
2008-04-21 10:02:58 +08:00
|
|
|
}
|
2008-12-16 07:53:10 +08:00
|
|
|
|
|
|
|
if (!Redeclaration && D.getCXXScopeSpec().isSet()) {
|
|
|
|
// The user tried to provide an out-of-line definition for a
|
|
|
|
// member function, but there was no such member function
|
|
|
|
// declared (C++ [class.mfct]p2). For example:
|
|
|
|
//
|
|
|
|
// class X {
|
|
|
|
// void f() const;
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// void X::f() { } // ill-formed
|
|
|
|
//
|
|
|
|
// Complain about this problem, and attempt to suggest close
|
|
|
|
// matches (e.g., those that differ only in cv-qualifiers and
|
|
|
|
// whether the parameter types are references).
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
|
|
|
|
<< cast<CXXRecordDecl>(DC)->getDeclName()
|
|
|
|
<< D.getCXXScopeSpec().getRange();
|
|
|
|
InvalidDecl = true;
|
|
|
|
|
|
|
|
PrevDecl = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC);
|
|
|
|
if (!PrevDecl) {
|
|
|
|
// Nothing to suggest.
|
|
|
|
} else if (OverloadedFunctionDecl *Ovl
|
|
|
|
= dyn_cast<OverloadedFunctionDecl>(PrevDecl)) {
|
|
|
|
for (OverloadedFunctionDecl::function_iterator
|
|
|
|
Func = Ovl->function_begin(),
|
|
|
|
FuncEnd = Ovl->function_end();
|
|
|
|
Func != FuncEnd; ++Func) {
|
|
|
|
if (isNearlyMatchingMemberFunction(Context, *Func, NewFD))
|
|
|
|
Diag((*Func)->getLocation(), diag::note_member_def_close_match);
|
|
|
|
|
|
|
|
}
|
|
|
|
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(PrevDecl)) {
|
|
|
|
// Suggest this no matter how mismatched it is; it's the only
|
|
|
|
// thing we have.
|
|
|
|
unsigned diag;
|
|
|
|
if (isNearlyMatchingMemberFunction(Context, Method, NewFD))
|
|
|
|
diag = diag::note_member_def_close_match;
|
|
|
|
else if (Method->getBody())
|
|
|
|
diag = diag::note_previous_definition;
|
|
|
|
else
|
|
|
|
diag = diag::note_previous_declaration;
|
|
|
|
Diag(Method->getLocation(), diag);
|
|
|
|
}
|
|
|
|
|
|
|
|
PrevDecl = 0;
|
|
|
|
}
|
2007-01-28 03:27:06 +08:00
|
|
|
}
|
2008-12-26 08:52:02 +08:00
|
|
|
// Handle attributes. We need to have merged decls when handling attributes
|
|
|
|
// (for example to check for conflicts, etc).
|
|
|
|
ProcessDeclAttributes(NewFD, D);
|
2007-01-28 03:27:06 +08:00
|
|
|
New = NewFD;
|
2008-04-08 12:40:51 +08:00
|
|
|
|
2008-12-16 07:53:10 +08:00
|
|
|
if (getLangOptions().CPlusPlus) {
|
|
|
|
// In C++, check default arguments now that we have merged decls.
|
2008-04-08 12:40:51 +08:00
|
|
|
CheckCXXDefaultArguments(NewFD);
|
2008-12-16 07:53:10 +08:00
|
|
|
|
|
|
|
// An out-of-line member function declaration must also be a
|
|
|
|
// definition (C++ [dcl.meaning]p1).
|
2008-12-24 05:05:05 +08:00
|
|
|
if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() && !InvalidDecl) {
|
2008-12-16 07:53:10 +08:00
|
|
|
Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
|
|
|
|
<< D.getCXXScopeSpec().getRange();
|
|
|
|
InvalidDecl = true;
|
|
|
|
}
|
|
|
|
}
|
2007-01-26 07:09:03 +08:00
|
|
|
} else {
|
2008-05-07 12:49:29 +08:00
|
|
|
// Check that there are no default arguments (C++ only).
|
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
CheckExtraCXXDefaultArguments(D);
|
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
if (R.getTypePtr()->isObjCInterfaceType()) {
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(D.getIdentifierLoc(), diag::err_statically_allocated_object)
|
|
|
|
<< D.getIdentifier();
|
2007-10-13 06:10:42 +08:00
|
|
|
InvalidDecl = true;
|
|
|
|
}
|
2007-01-28 03:27:06 +08:00
|
|
|
|
2007-04-04 07:13:13 +08:00
|
|
|
VarDecl *NewVD;
|
|
|
|
VarDecl::StorageClass SC;
|
2007-03-16 08:33:25 +08:00
|
|
|
switch (D.getDeclSpec().getStorageClassSpec()) {
|
2008-03-16 05:10:16 +08:00
|
|
|
default: assert(0 && "Unknown storage class!");
|
|
|
|
case DeclSpec::SCS_unspecified: SC = VarDecl::None; break;
|
|
|
|
case DeclSpec::SCS_extern: SC = VarDecl::Extern; break;
|
|
|
|
case DeclSpec::SCS_static: SC = VarDecl::Static; break;
|
|
|
|
case DeclSpec::SCS_auto: SC = VarDecl::Auto; break;
|
|
|
|
case DeclSpec::SCS_register: SC = VarDecl::Register; break;
|
|
|
|
case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
|
2008-11-15 07:42:31 +08:00
|
|
|
case DeclSpec::SCS_mutable:
|
|
|
|
// mutable can only appear on non-static class members, so it's always
|
|
|
|
// an error here
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
|
|
|
|
InvalidDecl = true;
|
2008-12-02 06:46:22 +08:00
|
|
|
SC = VarDecl::None;
|
2008-11-18 07:24:37 +08:00
|
|
|
break;
|
2008-11-15 07:42:31 +08:00
|
|
|
}
|
2008-11-18 06:58:34 +08:00
|
|
|
|
|
|
|
IdentifierInfo *II = Name.getAsIdentifierInfo();
|
|
|
|
if (!II) {
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
|
|
|
|
<< Name.getAsString();
|
2008-11-18 06:58:34 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-11-09 01:17:31 +08:00
|
|
|
if (DC->isCXXRecord()) {
|
2008-07-01 18:37:29 +08:00
|
|
|
// This is a static data member for a C++ class.
|
2008-11-09 01:17:31 +08:00
|
|
|
NewVD = CXXClassVarDecl::Create(Context, cast<CXXRecordDecl>(DC),
|
2008-07-01 18:37:29 +08:00
|
|
|
D.getIdentifierLoc(), II,
|
|
|
|
R, LastDeclarator);
|
2007-09-02 10:04:30 +08:00
|
|
|
} else {
|
2008-09-09 04:05:47 +08:00
|
|
|
bool ThreadSpecified = D.getDeclSpec().isThreadSpecified();
|
2008-07-01 18:37:29 +08:00
|
|
|
if (S->getFnParent() == 0) {
|
|
|
|
// C99 6.9p2: The storage-class specifiers auto and register shall not
|
|
|
|
// appear in the declaration specifiers in an external declaration.
|
|
|
|
if (SC == VarDecl::Auto || SC == VarDecl::Register) {
|
2008-11-24 14:25:27 +08:00
|
|
|
Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
|
2008-07-01 18:37:29 +08:00
|
|
|
InvalidDecl = true;
|
|
|
|
}
|
|
|
|
}
|
2008-11-15 07:42:31 +08:00
|
|
|
NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
|
|
|
|
II, R, SC, LastDeclarator,
|
|
|
|
// FIXME: Move to DeclGroup...
|
|
|
|
D.getDeclSpec().getSourceRange().getBegin());
|
|
|
|
NewVD->setThreadSpecified(ThreadSpecified);
|
2007-08-29 02:45:29 +08:00
|
|
|
}
|
2007-06-11 08:35:03 +08:00
|
|
|
// Handle attributes prior to checking for duplicates in MergeVarDecl
|
2008-06-29 08:02:00 +08:00
|
|
|
ProcessDeclAttributes(NewVD, D);
|
2008-03-15 02:07:10 +08:00
|
|
|
|
2008-08-06 08:03:29 +08:00
|
|
|
// Handle GNU asm-label extension (encoded as an attribute).
|
|
|
|
if (Expr *E = (Expr*) D.getAsmLabel()) {
|
|
|
|
// The parser guarantees this is a string.
|
|
|
|
StringLiteral *SE = cast<StringLiteral>(E);
|
|
|
|
NewVD->addAttr(new AsmLabelAttr(std::string(SE->getStrData(),
|
|
|
|
SE->getByteLength())));
|
|
|
|
}
|
|
|
|
|
2008-03-15 02:07:10 +08:00
|
|
|
// Emit an error if an address space was applied to decl with local storage.
|
|
|
|
// This includes arrays of objects with address space qualifiers, but not
|
|
|
|
// automatic variables that point to other address spaces.
|
|
|
|
// ISO/IEC TR 18037 S5.1.2
|
2008-03-26 02:36:32 +08:00
|
|
|
if (NewVD->hasLocalStorage() && (NewVD->getType().getAddressSpace() != 0)) {
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_as_qualified_auto_decl);
|
|
|
|
InvalidDecl = true;
|
2008-03-14 08:22:18 +08:00
|
|
|
}
|
2008-01-10 07:34:55 +08:00
|
|
|
// Merge the decl with the existing one if appropriate. If the decl is
|
|
|
|
// in an outer scope, it isn't the same thing.
|
2008-11-09 01:17:31 +08:00
|
|
|
if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
|
2008-12-16 07:53:10 +08:00
|
|
|
if (isa<FieldDecl>(PrevDecl) && D.getCXXScopeSpec().isSet()) {
|
|
|
|
// The user tried to define a non-static data member
|
|
|
|
// out-of-line (C++ [dcl.meaning]p1).
|
|
|
|
Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
|
|
|
|
<< D.getCXXScopeSpec().getRange();
|
|
|
|
NewVD->Destroy(Context);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-01-28 03:27:06 +08:00
|
|
|
NewVD = MergeVarDecl(NewVD, PrevDecl);
|
|
|
|
if (NewVD == 0) return 0;
|
2008-12-16 07:53:10 +08:00
|
|
|
|
|
|
|
if (D.getCXXScopeSpec().isSet()) {
|
|
|
|
// No previous declaration in the qualifying scope.
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
|
|
|
|
<< Name << D.getCXXScopeSpec().getRange();
|
|
|
|
InvalidDecl = true;
|
|
|
|
}
|
2007-01-28 03:27:06 +08:00
|
|
|
}
|
|
|
|
New = NewVD;
|
2007-01-26 07:09:03 +08:00
|
|
|
}
|
2006-11-19 10:31:38 +08:00
|
|
|
|
2008-11-10 07:41:00 +08:00
|
|
|
// Set the lexical context. If the declarator has a C++ scope specifier, the
|
|
|
|
// lexical context will be different from the semantic context.
|
|
|
|
New->setLexicalDeclContext(CurContext);
|
|
|
|
|
2006-11-10 13:29:30 +08:00
|
|
|
// If this has an identifier, add it to the scope stack.
|
2008-11-18 06:58:34 +08:00
|
|
|
if (Name)
|
2008-04-12 08:47:19 +08:00
|
|
|
PushOnScopeChains(New, S);
|
2007-08-29 04:14:24 +08:00
|
|
|
// If any semantic error occurred, mark the decl as invalid.
|
|
|
|
if (D.getInvalidType() || InvalidDecl)
|
|
|
|
New->setInvalidDecl();
|
2006-11-10 13:29:30 +08:00
|
|
|
|
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
2008-10-27 19:34:16 +08:00
|
|
|
void Sema::InitializerElementNotConstant(const Expr *Init) {
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
|
|
|
|
<< Init->getSourceRange();
|
2008-10-27 19:34:16 +08:00
|
|
|
}
|
|
|
|
|
2008-05-20 21:48:25 +08:00
|
|
|
bool Sema::CheckAddressConstantExpressionLValue(const Expr* Init) {
|
|
|
|
switch (Init->getStmtClass()) {
|
|
|
|
default:
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-01-11 06:15:12 +08:00
|
|
|
return true;
|
2008-05-20 21:48:25 +08:00
|
|
|
case Expr::ParenExprClass: {
|
|
|
|
const ParenExpr* PE = cast<ParenExpr>(Init);
|
|
|
|
return CheckAddressConstantExpressionLValue(PE->getSubExpr());
|
2008-01-11 06:15:12 +08:00
|
|
|
}
|
2008-05-20 21:48:25 +08:00
|
|
|
case Expr::CompoundLiteralExprClass:
|
|
|
|
return cast<CompoundLiteralExpr>(Init)->isFileScope();
|
|
|
|
case Expr::DeclRefExprClass: {
|
|
|
|
const Decl *D = cast<DeclRefExpr>(Init)->getDecl();
|
2008-05-21 11:39:11 +08:00
|
|
|
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
|
|
|
if (VD->hasGlobalStorage())
|
|
|
|
return false;
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-21 11:39:11 +08:00
|
|
|
return true;
|
|
|
|
}
|
2008-05-20 21:48:25 +08:00
|
|
|
if (isa<FunctionDecl>(D))
|
|
|
|
return false;
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case Expr::MemberExprClass: {
|
|
|
|
const MemberExpr *M = cast<MemberExpr>(Init);
|
|
|
|
if (M->isArrow())
|
|
|
|
return CheckAddressConstantExpression(M->getBase());
|
|
|
|
return CheckAddressConstantExpressionLValue(M->getBase());
|
|
|
|
}
|
|
|
|
case Expr::ArraySubscriptExprClass: {
|
|
|
|
// FIXME: Should we pedwarn for "x[0+0]" (where x is a pointer)?
|
|
|
|
const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(Init);
|
|
|
|
return CheckAddressConstantExpression(ASE->getBase()) ||
|
|
|
|
CheckArithmeticConstantExpression(ASE->getIdx());
|
|
|
|
}
|
|
|
|
case Expr::StringLiteralClass:
|
2008-08-10 09:53:14 +08:00
|
|
|
case Expr::PredefinedExprClass:
|
2008-05-20 21:48:25 +08:00
|
|
|
return false;
|
|
|
|
case Expr::UnaryOperatorClass: {
|
|
|
|
const UnaryOperator *Exp = cast<UnaryOperator>(Init);
|
|
|
|
|
|
|
|
// C99 6.6p9
|
|
|
|
if (Exp->getOpcode() == UnaryOperator::Deref)
|
2008-05-21 11:39:11 +08:00
|
|
|
return CheckAddressConstantExpression(Exp->getSubExpr());
|
2008-05-20 21:48:25 +08:00
|
|
|
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::CheckAddressConstantExpression(const Expr* Init) {
|
|
|
|
switch (Init->getStmtClass()) {
|
|
|
|
default:
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
2008-10-06 15:26:43 +08:00
|
|
|
case Expr::ParenExprClass:
|
|
|
|
return CheckAddressConstantExpression(cast<ParenExpr>(Init)->getSubExpr());
|
2008-05-20 21:48:25 +08:00
|
|
|
case Expr::StringLiteralClass:
|
|
|
|
case Expr::ObjCStringLiteralClass:
|
|
|
|
return false;
|
2008-10-06 15:26:43 +08:00
|
|
|
case Expr::CallExprClass:
|
2008-11-15 00:09:21 +08:00
|
|
|
case Expr::CXXOperatorCallExprClass:
|
2008-10-06 15:26:43 +08:00
|
|
|
// __builtin___CFStringMakeConstantString is a valid constant l-value.
|
|
|
|
if (cast<CallExpr>(Init)->isBuiltinCall() ==
|
|
|
|
Builtin::BI__builtin___CFStringMakeConstantString)
|
|
|
|
return false;
|
|
|
|
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-10-06 15:26:43 +08:00
|
|
|
return true;
|
|
|
|
|
2008-05-20 21:48:25 +08:00
|
|
|
case Expr::UnaryOperatorClass: {
|
|
|
|
const UnaryOperator *Exp = cast<UnaryOperator>(Init);
|
|
|
|
|
|
|
|
// C99 6.6p9
|
|
|
|
if (Exp->getOpcode() == UnaryOperator::AddrOf)
|
|
|
|
return CheckAddressConstantExpressionLValue(Exp->getSubExpr());
|
|
|
|
|
|
|
|
if (Exp->getOpcode() == UnaryOperator::Extension)
|
|
|
|
return CheckAddressConstantExpression(Exp->getSubExpr());
|
|
|
|
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case Expr::BinaryOperatorClass: {
|
|
|
|
// FIXME: Should we pedwarn for expressions like "a + 1 + 2"?
|
|
|
|
const BinaryOperator *Exp = cast<BinaryOperator>(Init);
|
|
|
|
|
|
|
|
Expr *PExp = Exp->getLHS();
|
|
|
|
Expr *IExp = Exp->getRHS();
|
|
|
|
if (IExp->getType()->isPointerType())
|
|
|
|
std::swap(PExp, IExp);
|
|
|
|
|
|
|
|
// FIXME: Should we pedwarn if IExp isn't an integer constant expression?
|
|
|
|
return CheckAddressConstantExpression(PExp) ||
|
|
|
|
CheckArithmeticConstantExpression(IExp);
|
|
|
|
}
|
2008-08-26 04:46:57 +08:00
|
|
|
case Expr::ImplicitCastExprClass:
|
2008-10-28 23:36:24 +08:00
|
|
|
case Expr::CStyleCastExprClass: {
|
2008-05-20 21:48:25 +08:00
|
|
|
const Expr* SubExpr = cast<CastExpr>(Init)->getSubExpr();
|
2008-08-26 04:46:57 +08:00
|
|
|
if (Init->getStmtClass() == Expr::ImplicitCastExprClass) {
|
|
|
|
// Check for implicit promotion
|
|
|
|
if (SubExpr->getType()->isFunctionType() ||
|
|
|
|
SubExpr->getType()->isArrayType())
|
|
|
|
return CheckAddressConstantExpressionLValue(SubExpr);
|
|
|
|
}
|
2008-05-20 21:48:25 +08:00
|
|
|
|
|
|
|
// Check for pointer->pointer cast
|
|
|
|
if (SubExpr->getType()->isPointerType())
|
|
|
|
return CheckAddressConstantExpression(SubExpr);
|
|
|
|
|
2008-08-26 04:46:57 +08:00
|
|
|
if (SubExpr->getType()->isIntegralType()) {
|
|
|
|
// Check for the special-case of a pointer->int->pointer cast;
|
|
|
|
// this isn't standard, but some code requires it. See
|
|
|
|
// PR2720 for an example.
|
|
|
|
if (const CastExpr* SubCast = dyn_cast<CastExpr>(SubExpr)) {
|
|
|
|
if (SubCast->getSubExpr()->getType()->isPointerType()) {
|
|
|
|
unsigned IntWidth = Context.getIntWidth(SubCast->getType());
|
|
|
|
unsigned PointerWidth = Context.getTypeSize(Context.VoidPtrTy);
|
|
|
|
if (IntWidth >= PointerWidth) {
|
|
|
|
return CheckAddressConstantExpression(SubCast->getSubExpr());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (SubExpr->getType()->isArithmeticType()) {
|
2008-05-20 21:48:25 +08:00
|
|
|
return CheckArithmeticConstantExpression(SubExpr);
|
2008-08-26 04:46:57 +08:00
|
|
|
}
|
2008-05-20 21:48:25 +08:00
|
|
|
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case Expr::ConditionalOperatorClass: {
|
|
|
|
// FIXME: Should we pedwarn here?
|
|
|
|
const ConditionalOperator *Exp = cast<ConditionalOperator>(Init);
|
|
|
|
if (!Exp->getCond()->getType()->isArithmeticType()) {
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (CheckArithmeticConstantExpression(Exp->getCond()))
|
|
|
|
return true;
|
|
|
|
if (Exp->getLHS() &&
|
|
|
|
CheckAddressConstantExpression(Exp->getLHS()))
|
|
|
|
return true;
|
|
|
|
return CheckAddressConstantExpression(Exp->getRHS());
|
|
|
|
}
|
|
|
|
case Expr::AddrLabelExprClass:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-09 13:05:07 +08:00
|
|
|
static const Expr* FindExpressionBaseAddress(const Expr* E);
|
|
|
|
|
|
|
|
static const Expr* FindExpressionBaseAddressLValue(const Expr* E) {
|
|
|
|
switch (E->getStmtClass()) {
|
|
|
|
default:
|
|
|
|
return E;
|
|
|
|
case Expr::ParenExprClass: {
|
|
|
|
const ParenExpr* PE = cast<ParenExpr>(E);
|
|
|
|
return FindExpressionBaseAddressLValue(PE->getSubExpr());
|
|
|
|
}
|
|
|
|
case Expr::MemberExprClass: {
|
|
|
|
const MemberExpr *M = cast<MemberExpr>(E);
|
|
|
|
if (M->isArrow())
|
|
|
|
return FindExpressionBaseAddress(M->getBase());
|
|
|
|
return FindExpressionBaseAddressLValue(M->getBase());
|
|
|
|
}
|
|
|
|
case Expr::ArraySubscriptExprClass: {
|
|
|
|
const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(E);
|
|
|
|
return FindExpressionBaseAddress(ASE->getBase());
|
|
|
|
}
|
|
|
|
case Expr::UnaryOperatorClass: {
|
|
|
|
const UnaryOperator *Exp = cast<UnaryOperator>(E);
|
|
|
|
|
|
|
|
if (Exp->getOpcode() == UnaryOperator::Deref)
|
|
|
|
return FindExpressionBaseAddress(Exp->getSubExpr());
|
|
|
|
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const Expr* FindExpressionBaseAddress(const Expr* E) {
|
|
|
|
switch (E->getStmtClass()) {
|
|
|
|
default:
|
|
|
|
return E;
|
|
|
|
case Expr::ParenExprClass: {
|
|
|
|
const ParenExpr* PE = cast<ParenExpr>(E);
|
|
|
|
return FindExpressionBaseAddress(PE->getSubExpr());
|
|
|
|
}
|
|
|
|
case Expr::UnaryOperatorClass: {
|
|
|
|
const UnaryOperator *Exp = cast<UnaryOperator>(E);
|
|
|
|
|
|
|
|
// C99 6.6p9
|
|
|
|
if (Exp->getOpcode() == UnaryOperator::AddrOf)
|
|
|
|
return FindExpressionBaseAddressLValue(Exp->getSubExpr());
|
|
|
|
|
|
|
|
if (Exp->getOpcode() == UnaryOperator::Extension)
|
|
|
|
return FindExpressionBaseAddress(Exp->getSubExpr());
|
|
|
|
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
case Expr::BinaryOperatorClass: {
|
|
|
|
const BinaryOperator *Exp = cast<BinaryOperator>(E);
|
|
|
|
|
|
|
|
Expr *PExp = Exp->getLHS();
|
|
|
|
Expr *IExp = Exp->getRHS();
|
|
|
|
if (IExp->getType()->isPointerType())
|
|
|
|
std::swap(PExp, IExp);
|
|
|
|
|
|
|
|
return FindExpressionBaseAddress(PExp);
|
|
|
|
}
|
|
|
|
case Expr::ImplicitCastExprClass: {
|
|
|
|
const Expr* SubExpr = cast<ImplicitCastExpr>(E)->getSubExpr();
|
|
|
|
|
|
|
|
// Check for implicit promotion
|
|
|
|
if (SubExpr->getType()->isFunctionType() ||
|
|
|
|
SubExpr->getType()->isArrayType())
|
|
|
|
return FindExpressionBaseAddressLValue(SubExpr);
|
|
|
|
|
|
|
|
// Check for pointer->pointer cast
|
|
|
|
if (SubExpr->getType()->isPointerType())
|
|
|
|
return FindExpressionBaseAddress(SubExpr);
|
|
|
|
|
|
|
|
// We assume that we have an arithmetic expression here;
|
|
|
|
// if we don't, we'll figure it out later
|
|
|
|
return 0;
|
|
|
|
}
|
2008-10-28 23:36:24 +08:00
|
|
|
case Expr::CStyleCastExprClass: {
|
2008-06-09 13:05:07 +08:00
|
|
|
const Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
|
|
|
|
|
|
|
|
// Check for pointer->pointer cast
|
|
|
|
if (SubExpr->getType()->isPointerType())
|
|
|
|
return FindExpressionBaseAddress(SubExpr);
|
|
|
|
|
|
|
|
// We assume that we have an arithmetic expression here;
|
|
|
|
// if we don't, we'll figure it out later
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-23 05:04:56 +08:00
|
|
|
bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {
|
2008-05-20 21:48:25 +08:00
|
|
|
switch (Init->getStmtClass()) {
|
|
|
|
default:
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
case Expr::ParenExprClass: {
|
|
|
|
const ParenExpr* PE = cast<ParenExpr>(Init);
|
|
|
|
return CheckArithmeticConstantExpression(PE->getSubExpr());
|
|
|
|
}
|
|
|
|
case Expr::FloatingLiteralClass:
|
|
|
|
case Expr::IntegerLiteralClass:
|
|
|
|
case Expr::CharacterLiteralClass:
|
|
|
|
case Expr::ImaginaryLiteralClass:
|
|
|
|
case Expr::TypesCompatibleExprClass:
|
|
|
|
case Expr::CXXBoolLiteralExprClass:
|
|
|
|
return false;
|
2008-11-15 00:09:21 +08:00
|
|
|
case Expr::CallExprClass:
|
|
|
|
case Expr::CXXOperatorCallExprClass: {
|
2008-05-20 21:48:25 +08:00
|
|
|
const CallExpr *CE = cast<CallExpr>(Init);
|
2008-10-06 14:49:02 +08:00
|
|
|
|
|
|
|
// Allow any constant foldable calls to builtins.
|
|
|
|
if (CE->isBuiltinCall() && CE->isEvaluatable(Context))
|
2008-05-20 21:48:25 +08:00
|
|
|
return false;
|
2008-10-06 14:49:02 +08:00
|
|
|
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case Expr::DeclRefExprClass: {
|
|
|
|
const Decl *D = cast<DeclRefExpr>(Init)->getDecl();
|
|
|
|
if (isa<EnumConstantDecl>(D))
|
|
|
|
return false;
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case Expr::CompoundLiteralExprClass:
|
|
|
|
// Allow "(vector type){2,4}"; normal C constraints don't allow this,
|
|
|
|
// but vectors are allowed to be magic.
|
|
|
|
if (Init->getType()->isVectorType())
|
|
|
|
return false;
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
case Expr::UnaryOperatorClass: {
|
|
|
|
const UnaryOperator *Exp = cast<UnaryOperator>(Init);
|
|
|
|
|
|
|
|
switch (Exp->getOpcode()) {
|
|
|
|
// Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
|
|
|
|
// See C99 6.6p3.
|
|
|
|
default:
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
case UnaryOperator::OffsetOf:
|
|
|
|
if (Exp->getSubExpr()->getType()->isConstantSizeType())
|
|
|
|
return false;
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
case UnaryOperator::Extension:
|
|
|
|
case UnaryOperator::LNot:
|
|
|
|
case UnaryOperator::Plus:
|
|
|
|
case UnaryOperator::Minus:
|
|
|
|
case UnaryOperator::Not:
|
|
|
|
return CheckArithmeticConstantExpression(Exp->getSubExpr());
|
|
|
|
}
|
|
|
|
}
|
2008-11-12 01:56:53 +08:00
|
|
|
case Expr::SizeOfAlignOfExprClass: {
|
|
|
|
const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
// Special check for void types, which are allowed as an extension
|
2008-11-12 01:56:53 +08:00
|
|
|
if (Exp->getTypeOfArgument()->isVoidType())
|
2008-05-20 21:48:25 +08:00
|
|
|
return false;
|
|
|
|
// alignof always evaluates to a constant.
|
|
|
|
// FIXME: is sizeof(int[3.0]) a constant expression?
|
2008-11-12 01:56:53 +08:00
|
|
|
if (Exp->isSizeOf() && !Exp->getTypeOfArgument()->isConstantSizeType()) {
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
case Expr::BinaryOperatorClass: {
|
|
|
|
const BinaryOperator *Exp = cast<BinaryOperator>(Init);
|
|
|
|
|
|
|
|
if (Exp->getLHS()->getType()->isArithmeticType() &&
|
|
|
|
Exp->getRHS()->getType()->isArithmeticType()) {
|
|
|
|
return CheckArithmeticConstantExpression(Exp->getLHS()) ||
|
|
|
|
CheckArithmeticConstantExpression(Exp->getRHS());
|
|
|
|
}
|
|
|
|
|
2008-06-09 13:05:07 +08:00
|
|
|
if (Exp->getLHS()->getType()->isPointerType() &&
|
|
|
|
Exp->getRHS()->getType()->isPointerType()) {
|
|
|
|
const Expr* LHSBase = FindExpressionBaseAddress(Exp->getLHS());
|
|
|
|
const Expr* RHSBase = FindExpressionBaseAddress(Exp->getRHS());
|
|
|
|
|
|
|
|
// Only allow a null (constant integer) base; we could
|
|
|
|
// allow some additional cases if necessary, but this
|
|
|
|
// is sufficient to cover offsetof-like constructs.
|
|
|
|
if (!LHSBase && !RHSBase) {
|
|
|
|
return CheckAddressConstantExpression(Exp->getLHS()) ||
|
|
|
|
CheckAddressConstantExpression(Exp->getRHS());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case Expr::ImplicitCastExprClass:
|
2008-10-28 23:36:24 +08:00
|
|
|
case Expr::CStyleCastExprClass: {
|
2008-08-19 07:01:59 +08:00
|
|
|
const Expr *SubExpr = cast<CastExpr>(Init)->getSubExpr();
|
2008-09-02 06:08:17 +08:00
|
|
|
if (SubExpr->getType()->isArithmeticType())
|
|
|
|
return CheckArithmeticConstantExpression(SubExpr);
|
|
|
|
|
2008-09-02 17:37:00 +08:00
|
|
|
if (SubExpr->getType()->isPointerType()) {
|
|
|
|
const Expr* Base = FindExpressionBaseAddress(SubExpr);
|
|
|
|
// If the pointer has a null base, this is an offsetof-like construct
|
|
|
|
if (!Base)
|
|
|
|
return CheckAddressConstantExpression(SubExpr);
|
|
|
|
}
|
|
|
|
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-09-02 06:08:17 +08:00
|
|
|
return true;
|
2008-05-20 21:48:25 +08:00
|
|
|
}
|
|
|
|
case Expr::ConditionalOperatorClass: {
|
|
|
|
const ConditionalOperator *Exp = cast<ConditionalOperator>(Init);
|
2008-10-06 13:42:39 +08:00
|
|
|
|
|
|
|
// If GNU extensions are disabled, we require all operands to be arithmetic
|
|
|
|
// constant expressions.
|
|
|
|
if (getLangOptions().NoExtensions) {
|
|
|
|
return CheckArithmeticConstantExpression(Exp->getCond()) ||
|
|
|
|
(Exp->getLHS() && CheckArithmeticConstantExpression(Exp->getLHS())) ||
|
|
|
|
CheckArithmeticConstantExpression(Exp->getRHS());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we have to emulate some of the behavior of fold here.
|
|
|
|
// Basically GCC treats things like "4 ? 1 : somefunc()" as a constant
|
|
|
|
// because it can constant fold things away. To retain compatibility with
|
|
|
|
// GCC code, we see if we can fold the condition to a constant (which we
|
|
|
|
// should always be able to do in theory). If so, we only require the
|
|
|
|
// specified arm of the conditional to be a constant. This is a horrible
|
|
|
|
// hack, but is require by real world code that uses __builtin_constant_p.
|
2008-12-20 04:58:05 +08:00
|
|
|
Expr::EvalResult EvalResult;
|
|
|
|
if (!Exp->getCond()->Evaluate(EvalResult, Context) ||
|
|
|
|
EvalResult.HasSideEffects) {
|
2008-11-17 05:24:15 +08:00
|
|
|
// If Evaluate couldn't fold it, CheckArithmeticConstantExpression
|
2008-10-06 13:42:39 +08:00
|
|
|
// won't be able to either. Use it to emit the diagnostic though.
|
|
|
|
bool Res = CheckArithmeticConstantExpression(Exp->getCond());
|
2008-11-17 05:24:15 +08:00
|
|
|
assert(Res && "Evaluate couldn't evaluate this constant?");
|
2008-10-06 13:42:39 +08:00
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that the side following the condition is also a constant.
|
|
|
|
const Expr *TrueSide = Exp->getLHS(), *FalseSide = Exp->getRHS();
|
2008-12-20 04:58:05 +08:00
|
|
|
if (EvalResult.Val.getInt() == 0)
|
2008-10-06 13:42:39 +08:00
|
|
|
std::swap(TrueSide, FalseSide);
|
|
|
|
|
|
|
|
if (TrueSide && CheckArithmeticConstantExpression(TrueSide))
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
2008-10-06 13:42:39 +08:00
|
|
|
|
|
|
|
// Okay, the evaluated side evaluates to a constant, so we accept this.
|
|
|
|
// Check to see if the other side is obviously not a constant. If so,
|
|
|
|
// emit a warning that this is a GNU extension.
|
2008-10-06 14:49:02 +08:00
|
|
|
if (FalseSide && !FalseSide->isEvaluatable(Context))
|
2008-10-06 13:42:39 +08:00
|
|
|
Diag(Init->getExprLoc(),
|
2008-11-19 13:27:50 +08:00
|
|
|
diag::ext_typecheck_expression_not_constant_but_accepted)
|
|
|
|
<< FalseSide->getSourceRange();
|
2008-10-06 13:42:39 +08:00
|
|
|
return false;
|
2008-05-20 21:48:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
|
2008-12-05 13:09:56 +08:00
|
|
|
Expr::EvalResult Result;
|
|
|
|
|
2008-07-08 00:46:50 +08:00
|
|
|
Init = Init->IgnoreParens();
|
|
|
|
|
2008-12-05 13:09:56 +08:00
|
|
|
if (Init->Evaluate(Result, Context) && !Result.HasSideEffects)
|
|
|
|
return false;
|
|
|
|
|
2008-05-20 21:48:25 +08:00
|
|
|
// Look through CXXDefaultArgExprs; they have no meaning in this context.
|
|
|
|
if (CXXDefaultArgExpr* DAE = dyn_cast<CXXDefaultArgExpr>(Init))
|
|
|
|
return CheckForConstantInitializer(DAE->getExpr(), DclT);
|
|
|
|
|
2008-07-08 00:46:50 +08:00
|
|
|
if (CompoundLiteralExpr *e = dyn_cast<CompoundLiteralExpr>(Init))
|
|
|
|
return CheckForConstantInitializer(e->getInitializer(), DclT);
|
|
|
|
|
2008-05-20 21:48:25 +08:00
|
|
|
if (InitListExpr *Exp = dyn_cast<InitListExpr>(Init)) {
|
|
|
|
unsigned numInits = Exp->getNumInits();
|
|
|
|
for (unsigned i = 0; i < numInits; i++) {
|
|
|
|
// FIXME: Need to get the type of the declaration for C++,
|
|
|
|
// because it could be a reference?
|
|
|
|
if (CheckForConstantInitializer(Exp->getInit(i),
|
|
|
|
Exp->getInit(i)->getType()))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-12-05 13:09:56 +08:00
|
|
|
// FIXME: We can probably remove some of this code below, now that
|
|
|
|
// Expr::Evaluate is doing the heavy lifting for scalars.
|
|
|
|
|
2008-05-20 21:48:25 +08:00
|
|
|
if (Init->isNullPointerConstant(Context))
|
|
|
|
return false;
|
|
|
|
if (Init->getType()->isArithmeticType()) {
|
2008-07-27 06:17:49 +08:00
|
|
|
QualType InitTy = Context.getCanonicalType(Init->getType())
|
|
|
|
.getUnqualifiedType();
|
2008-05-31 02:14:48 +08:00
|
|
|
if (InitTy == Context.BoolTy) {
|
|
|
|
// Special handling for pointers implicitly cast to bool;
|
|
|
|
// (e.g. "_Bool rr = &rr;"). This is only legal at the top level.
|
|
|
|
if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(Init)) {
|
|
|
|
Expr* SubE = ICE->getSubExpr();
|
|
|
|
if (SubE->getType()->isPointerType() ||
|
|
|
|
SubE->getType()->isArrayType() ||
|
|
|
|
SubE->getType()->isFunctionType()) {
|
|
|
|
return CheckAddressConstantExpression(Init);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (InitTy->isIntegralType()) {
|
|
|
|
Expr* SubE = 0;
|
2008-08-19 07:01:59 +08:00
|
|
|
if (CastExpr* CE = dyn_cast<CastExpr>(Init))
|
2008-05-31 02:14:48 +08:00
|
|
|
SubE = CE->getSubExpr();
|
|
|
|
// Special check for pointer cast to int; we allow as an extension
|
|
|
|
// an address constant cast to an integer if the integer
|
|
|
|
// is of an appropriate width (this sort of code is apparently used
|
|
|
|
// in some places).
|
|
|
|
// FIXME: Add pedwarn?
|
|
|
|
// FIXME: Don't allow bitfields here! Need the FieldDecl for that.
|
|
|
|
if (SubE && (SubE->getType()->isPointerType() ||
|
|
|
|
SubE->getType()->isArrayType() ||
|
|
|
|
SubE->getType()->isFunctionType())) {
|
|
|
|
unsigned IntWidth = Context.getTypeSize(Init->getType());
|
|
|
|
unsigned PointerWidth = Context.getTypeSize(Context.VoidPtrTy);
|
|
|
|
if (IntWidth >= PointerWidth)
|
|
|
|
return CheckAddressConstantExpression(Init);
|
|
|
|
}
|
2008-05-20 21:48:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return CheckArithmeticConstantExpression(Init);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Init->getType()->isPointerType())
|
|
|
|
return CheckAddressConstantExpression(Init);
|
|
|
|
|
2008-05-31 02:14:48 +08:00
|
|
|
// An array type at the top level that isn't an init-list must
|
|
|
|
// be a string literal
|
2008-05-20 21:48:25 +08:00
|
|
|
if (Init->getType()->isArrayType())
|
|
|
|
return false;
|
|
|
|
|
2008-09-02 02:42:41 +08:00
|
|
|
if (Init->getType()->isFunctionType())
|
|
|
|
return false;
|
|
|
|
|
2008-10-03 01:12:56 +08:00
|
|
|
// Allow block exprs at top level.
|
|
|
|
if (Init->getType()->isBlockPointerType())
|
|
|
|
return false;
|
|
|
|
|
2008-10-27 19:34:16 +08:00
|
|
|
InitializerElementNotConstant(Init);
|
2008-05-20 21:48:25 +08:00
|
|
|
return true;
|
2008-01-11 06:15:12 +08:00
|
|
|
}
|
|
|
|
|
2008-12-14 00:23:55 +08:00
|
|
|
void Sema::AddInitializerToDecl(DeclTy *dcl, ExprArg init) {
|
2007-09-13 04:13:48 +08:00
|
|
|
Decl *RealDecl = static_cast<Decl *>(dcl);
|
2008-12-14 00:23:55 +08:00
|
|
|
Expr *Init = static_cast<Expr *>(init.release());
|
2007-10-20 04:10:30 +08:00
|
|
|
assert(Init && "missing initializer");
|
2007-09-12 22:07:44 +08:00
|
|
|
|
2007-10-20 04:10:30 +08:00
|
|
|
// If there is no declaration, there was an error parsing it. Just ignore
|
|
|
|
// the initializer.
|
|
|
|
if (RealDecl == 0) {
|
|
|
|
delete Init;
|
|
|
|
return;
|
|
|
|
}
|
2007-09-12 22:07:44 +08:00
|
|
|
|
2007-09-13 04:13:48 +08:00
|
|
|
VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
|
|
|
|
if (!VDecl) {
|
2007-09-14 05:41:19 +08:00
|
|
|
Diag(dyn_cast<ScopedDecl>(RealDecl)->getLocation(),
|
|
|
|
diag::err_illegal_initializer);
|
2007-09-13 04:13:48 +08:00
|
|
|
RealDecl->setInvalidDecl();
|
|
|
|
return;
|
|
|
|
}
|
2007-09-12 22:07:44 +08:00
|
|
|
// Get the decls type and save a reference for later, since
|
2008-01-11 06:15:12 +08:00
|
|
|
// CheckInitializerTypes may change it.
|
2007-09-13 04:13:48 +08:00
|
|
|
QualType DclT = VDecl->getType(), SavT = DclT;
|
2008-04-16 06:42:06 +08:00
|
|
|
if (VDecl->isBlockVarDecl()) {
|
|
|
|
VarDecl::StorageClass SC = VDecl->getStorageClass();
|
2007-09-12 22:07:44 +08:00
|
|
|
if (SC == VarDecl::Extern) { // C99 6.7.8p5
|
2007-09-13 04:13:48 +08:00
|
|
|
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
|
2008-04-16 06:42:06 +08:00
|
|
|
VDecl->setInvalidDecl();
|
|
|
|
} else if (!VDecl->isInvalidDecl()) {
|
2008-11-05 23:29:30 +08:00
|
|
|
if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
|
2008-11-24 13:29:24 +08:00
|
|
|
VDecl->getDeclName()))
|
2008-04-16 06:42:06 +08:00
|
|
|
VDecl->setInvalidDecl();
|
2008-08-22 13:00:02 +08:00
|
|
|
|
|
|
|
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
|
|
|
|
if (!getLangOptions().CPlusPlus) {
|
|
|
|
if (SC == VarDecl::Static) // C99 6.7.8p4.
|
|
|
|
CheckForConstantInitializer(Init, DclT);
|
|
|
|
}
|
2007-09-12 22:07:44 +08:00
|
|
|
}
|
2008-04-16 06:42:06 +08:00
|
|
|
} else if (VDecl->isFileVarDecl()) {
|
|
|
|
if (VDecl->getStorageClass() == VarDecl::Extern)
|
2007-09-13 04:13:48 +08:00
|
|
|
Diag(VDecl->getLocation(), diag::warn_extern_init);
|
2008-04-16 06:42:06 +08:00
|
|
|
if (!VDecl->isInvalidDecl())
|
2008-11-05 23:29:30 +08:00
|
|
|
if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
|
2008-11-24 13:29:24 +08:00
|
|
|
VDecl->getDeclName()))
|
2008-04-16 06:42:06 +08:00
|
|
|
VDecl->setInvalidDecl();
|
2008-01-11 06:15:12 +08:00
|
|
|
|
2008-08-22 13:00:02 +08:00
|
|
|
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
|
|
|
|
if (!getLangOptions().CPlusPlus) {
|
|
|
|
// C99 6.7.8p4. All file scoped initializers need to be constant.
|
|
|
|
CheckForConstantInitializer(Init, DclT);
|
|
|
|
}
|
2007-09-12 22:07:44 +08:00
|
|
|
}
|
|
|
|
// If the type changed, it means we had an incomplete type that was
|
|
|
|
// completed by the initializer. For example:
|
|
|
|
// int ary[] = { 1, 3, 5 };
|
|
|
|
// "ary" transitions from a VariableArrayType to a ConstantArrayType.
|
2007-11-30 03:09:19 +08:00
|
|
|
if (!VDecl->isInvalidDecl() && (DclT != SavT)) {
|
2007-09-13 04:13:48 +08:00
|
|
|
VDecl->setType(DclT);
|
2007-11-30 03:09:19 +08:00
|
|
|
Init->setType(DclT);
|
|
|
|
}
|
2007-09-12 22:07:44 +08:00
|
|
|
|
|
|
|
// Attach the initializer to the decl.
|
2007-09-13 04:13:48 +08:00
|
|
|
VDecl->setInit(Init);
|
2007-09-12 22:07:44 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-10-29 08:13:59 +08:00
|
|
|
void Sema::ActOnUninitializedDecl(DeclTy *dcl) {
|
|
|
|
Decl *RealDecl = static_cast<Decl *>(dcl);
|
|
|
|
|
2008-11-07 21:01:22 +08:00
|
|
|
// If there is no declaration, there was an error parsing it. Just ignore it.
|
|
|
|
if (RealDecl == 0)
|
|
|
|
return;
|
|
|
|
|
2008-10-29 08:13:59 +08:00
|
|
|
if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
|
|
|
|
QualType Type = Var->getType();
|
|
|
|
// C++ [dcl.init.ref]p3:
|
|
|
|
// The initializer can be omitted for a reference only in a
|
|
|
|
// parameter declaration (8.3.5), in the declaration of a
|
|
|
|
// function return type, in the declaration of a class member
|
|
|
|
// within its class declaration (9.2), and where the extern
|
|
|
|
// specifier is explicitly used.
|
2008-12-16 05:24:18 +08:00
|
|
|
if (Type->isReferenceType() &&
|
|
|
|
Var->getStorageClass() != VarDecl::Extern &&
|
|
|
|
Var->getStorageClass() != VarDecl::PrivateExtern) {
|
2008-11-20 14:06:08 +08:00
|
|
|
Diag(Var->getLocation(), diag::err_reference_var_requires_init)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< Var->getDeclName()
|
|
|
|
<< SourceRange(Var->getLocation(), Var->getLocation());
|
2008-11-04 04:45:27 +08:00
|
|
|
Var->setInvalidDecl();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// C++ [dcl.init]p9:
|
|
|
|
//
|
|
|
|
// If no initializer is specified for an object, and the object
|
|
|
|
// is of (possibly cv-qualified) non-POD class type (or array
|
|
|
|
// thereof), the object shall be default-initialized; if the
|
|
|
|
// object is of const-qualified type, the underlying class type
|
|
|
|
// shall have a user-declared default constructor.
|
|
|
|
if (getLangOptions().CPlusPlus) {
|
|
|
|
QualType InitType = Type;
|
|
|
|
if (const ArrayType *Array = Context.getAsArrayType(Type))
|
|
|
|
InitType = Array->getElementType();
|
2008-12-16 05:24:18 +08:00
|
|
|
if (Var->getStorageClass() != VarDecl::Extern &&
|
|
|
|
Var->getStorageClass() != VarDecl::PrivateExtern &&
|
|
|
|
InitType->isRecordType()) {
|
2008-11-05 23:29:30 +08:00
|
|
|
const CXXConstructorDecl *Constructor
|
|
|
|
= PerformInitializationByConstructor(InitType, 0, 0,
|
|
|
|
Var->getLocation(),
|
|
|
|
SourceRange(Var->getLocation(),
|
|
|
|
Var->getLocation()),
|
2008-11-24 13:29:24 +08:00
|
|
|
Var->getDeclName(),
|
2008-11-05 23:29:30 +08:00
|
|
|
IK_Default);
|
2008-11-04 04:45:27 +08:00
|
|
|
if (!Constructor)
|
|
|
|
Var->setInvalidDecl();
|
|
|
|
}
|
|
|
|
}
|
2008-10-29 08:13:59 +08:00
|
|
|
|
2008-10-29 21:50:18 +08:00
|
|
|
#if 0
|
|
|
|
// FIXME: Temporarily disabled because we are not properly parsing
|
|
|
|
// linkage specifications on declarations, e.g.,
|
|
|
|
//
|
|
|
|
// extern "C" const CGPoint CGPointerZero;
|
|
|
|
//
|
2008-10-29 08:13:59 +08:00
|
|
|
// C++ [dcl.init]p9:
|
|
|
|
//
|
|
|
|
// If no initializer is specified for an object, and the
|
|
|
|
// object is of (possibly cv-qualified) non-POD class type (or
|
|
|
|
// array thereof), the object shall be default-initialized; if
|
|
|
|
// the object is of const-qualified type, the underlying class
|
|
|
|
// type shall have a user-declared default
|
|
|
|
// constructor. Otherwise, if no initializer is specified for
|
|
|
|
// an object, the object and its subobjects, if any, have an
|
|
|
|
// indeterminate initial value; if the object or any of its
|
|
|
|
// subobjects are of const-qualified type, the program is
|
|
|
|
// ill-formed.
|
|
|
|
//
|
|
|
|
// This isn't technically an error in C, so we don't diagnose it.
|
|
|
|
//
|
|
|
|
// FIXME: Actually perform the POD/user-defined default
|
|
|
|
// constructor check.
|
|
|
|
if (getLangOptions().CPlusPlus &&
|
2008-10-29 21:50:18 +08:00
|
|
|
Context.getCanonicalType(Type).isConstQualified() &&
|
|
|
|
Var->getStorageClass() != VarDecl::Extern)
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(Var->getLocation(), diag::err_const_var_requires_init)
|
|
|
|
<< Var->getName()
|
|
|
|
<< SourceRange(Var->getLocation(), Var->getLocation());
|
2008-10-29 21:50:18 +08:00
|
|
|
#endif
|
2008-10-29 08:13:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-09 08:53:06 +08:00
|
|
|
/// The declarators are chained together backwards, reverse the list.
|
|
|
|
Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
|
|
|
|
// Often we have single declarators, handle them quickly.
|
2007-09-14 07:52:58 +08:00
|
|
|
Decl *GroupDecl = static_cast<Decl*>(group);
|
|
|
|
if (GroupDecl == 0)
|
2007-09-12 22:07:44 +08:00
|
|
|
return 0;
|
2007-09-14 07:52:58 +08:00
|
|
|
|
|
|
|
ScopedDecl *Group = dyn_cast<ScopedDecl>(GroupDecl);
|
|
|
|
ScopedDecl *NewGroup = 0;
|
2007-09-12 22:07:44 +08:00
|
|
|
if (Group->getNextDeclarator() == 0)
|
2007-06-09 08:53:06 +08:00
|
|
|
NewGroup = Group;
|
2007-09-12 22:07:44 +08:00
|
|
|
else { // reverse the list.
|
|
|
|
while (Group) {
|
2007-09-14 07:52:58 +08:00
|
|
|
ScopedDecl *Next = Group->getNextDeclarator();
|
2007-09-12 22:07:44 +08:00
|
|
|
Group->setNextDeclarator(NewGroup);
|
|
|
|
NewGroup = Group;
|
|
|
|
Group = Next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Perform semantic analysis that depends on having fully processed both
|
|
|
|
// the declarator and initializer.
|
2007-09-14 07:52:58 +08:00
|
|
|
for (ScopedDecl *ID = NewGroup; ID; ID = ID->getNextDeclarator()) {
|
2007-09-12 22:07:44 +08:00
|
|
|
VarDecl *IDecl = dyn_cast<VarDecl>(ID);
|
|
|
|
if (!IDecl)
|
|
|
|
continue;
|
|
|
|
QualType T = IDecl->getType();
|
|
|
|
|
2008-12-07 08:20:55 +08:00
|
|
|
if (T->isVariableArrayType()) {
|
2008-12-21 05:51:53 +08:00
|
|
|
const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
|
2008-12-07 08:49:48 +08:00
|
|
|
|
|
|
|
// FIXME: This won't give the correct result for
|
|
|
|
// int a[10][n];
|
|
|
|
SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
|
2008-12-07 08:20:55 +08:00
|
|
|
if (IDecl->isFileVarDecl()) {
|
2008-12-07 08:49:48 +08:00
|
|
|
Diag(IDecl->getLocation(), diag::err_vla_decl_in_file_scope) <<
|
|
|
|
SizeRange;
|
|
|
|
|
2008-02-16 02:16:39 +08:00
|
|
|
IDecl->setInvalidDecl();
|
2008-12-07 08:20:55 +08:00
|
|
|
} else {
|
|
|
|
// C99 6.7.5.2p2: If an identifier is declared to be an object with
|
|
|
|
// static storage duration, it shall not have a variable length array.
|
|
|
|
if (IDecl->getStorageClass() == VarDecl::Static) {
|
2008-12-07 08:49:48 +08:00
|
|
|
Diag(IDecl->getLocation(), diag::err_vla_decl_has_static_storage)
|
|
|
|
<< SizeRange;
|
2008-12-07 08:20:55 +08:00
|
|
|
IDecl->setInvalidDecl();
|
|
|
|
} else if (IDecl->getStorageClass() == VarDecl::Extern) {
|
2008-12-07 08:49:48 +08:00
|
|
|
Diag(IDecl->getLocation(), diag::err_vla_decl_has_extern_linkage)
|
|
|
|
<< SizeRange;
|
2008-12-07 08:20:55 +08:00
|
|
|
IDecl->setInvalidDecl();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (T->isVariablyModifiedType()) {
|
|
|
|
if (IDecl->isFileVarDecl()) {
|
|
|
|
Diag(IDecl->getLocation(), diag::err_vm_decl_in_file_scope);
|
|
|
|
IDecl->setInvalidDecl();
|
|
|
|
} else {
|
|
|
|
if (IDecl->getStorageClass() == VarDecl::Extern) {
|
|
|
|
Diag(IDecl->getLocation(), diag::err_vm_decl_has_extern_linkage);
|
|
|
|
IDecl->setInvalidDecl();
|
|
|
|
}
|
2007-09-12 22:07:44 +08:00
|
|
|
}
|
|
|
|
}
|
2008-12-07 08:20:55 +08:00
|
|
|
|
2007-09-12 22:07:44 +08:00
|
|
|
// Block scope. C99 6.7p7: If an identifier for an object is declared with
|
|
|
|
// no linkage (C99 6.2.2p6), the type for the object shall be complete...
|
2008-04-16 06:42:06 +08:00
|
|
|
if (IDecl->isBlockVarDecl() &&
|
|
|
|
IDecl->getStorageClass() != VarDecl::Extern) {
|
2008-04-02 09:05:10 +08:00
|
|
|
if (T->isIncompleteType() && !IDecl->isInvalidDecl()) {
|
2008-11-24 13:29:24 +08:00
|
|
|
Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type)<<T;
|
2007-09-12 22:07:44 +08:00
|
|
|
IDecl->setInvalidDecl();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// File scope. C99 6.9.2p2: A declaration of an identifier for and
|
|
|
|
// object that has file scope without an initializer, and without a
|
|
|
|
// storage-class specifier or with the storage-class specifier "static",
|
|
|
|
// constitutes a tentative definition. Note: A tentative definition with
|
|
|
|
// external linkage is valid (C99 6.2.2p5).
|
2008-08-09 01:50:35 +08:00
|
|
|
if (isTentativeDefinition(IDecl)) {
|
2008-02-15 20:53:51 +08:00
|
|
|
if (T->isIncompleteArrayType()) {
|
2008-01-19 04:40:52 +08:00
|
|
|
// C99 6.9.2 (p2, p5): Implicit initialization causes an incomplete
|
|
|
|
// array to be completed. Don't issue a diagnostic.
|
2008-04-02 09:05:10 +08:00
|
|
|
} else if (T->isIncompleteType() && !IDecl->isInvalidDecl()) {
|
2008-01-19 04:40:52 +08:00
|
|
|
// C99 6.9.2p3: If the declaration of an identifier for an object is
|
|
|
|
// a tentative definition and has internal linkage (C99 6.2.2p3), the
|
|
|
|
// declared type shall not be an incomplete type.
|
2008-11-24 13:29:24 +08:00
|
|
|
Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type)<<T;
|
2007-09-12 22:07:44 +08:00
|
|
|
IDecl->setInvalidDecl();
|
|
|
|
}
|
|
|
|
}
|
2008-08-09 01:50:35 +08:00
|
|
|
if (IDecl->isFileVarDecl())
|
|
|
|
CheckForFileScopedRedefinitions(S, IDecl);
|
2007-06-09 08:53:06 +08:00
|
|
|
}
|
|
|
|
return NewGroup;
|
|
|
|
}
|
2007-08-28 11:03:08 +08:00
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator()
|
|
|
|
/// to introduce parameters into function prototype scope.
|
|
|
|
Sema::DeclTy *
|
|
|
|
Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
|
2008-06-26 14:49:43 +08:00
|
|
|
const DeclSpec &DS = D.getDeclSpec();
|
2008-12-16 07:53:10 +08:00
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
// Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
|
2008-09-04 05:54:21 +08:00
|
|
|
VarDecl::StorageClass StorageClass = VarDecl::None;
|
|
|
|
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
|
|
|
|
StorageClass = VarDecl::Register;
|
|
|
|
} else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
|
2008-04-08 12:40:51 +08:00
|
|
|
Diag(DS.getStorageClassSpecLoc(),
|
|
|
|
diag::err_invalid_storage_class_in_func_decl);
|
2008-06-26 14:49:43 +08:00
|
|
|
D.getMutableDeclSpec().ClearStorageClassSpecs();
|
2008-04-08 12:40:51 +08:00
|
|
|
}
|
|
|
|
if (DS.isThreadSpecified()) {
|
|
|
|
Diag(DS.getThreadSpecLoc(),
|
|
|
|
diag::err_invalid_storage_class_in_func_decl);
|
2008-06-26 14:49:43 +08:00
|
|
|
D.getMutableDeclSpec().ClearStorageClassSpecs();
|
2008-04-08 12:40:51 +08:00
|
|
|
}
|
|
|
|
|
2008-05-07 12:49:29 +08:00
|
|
|
// Check that there are no default arguments inside the type of this
|
|
|
|
// parameter (C++ only).
|
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
CheckExtraCXXDefaultArguments(D);
|
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
// In this context, we *do not* check D.getInvalidType(). If the declarator
|
|
|
|
// type was invalid, GetTypeForDeclarator() still returns a "valid" type,
|
|
|
|
// though it will not reflect the user specified type.
|
|
|
|
QualType parmDeclType = GetTypeForDeclarator(D, S);
|
|
|
|
|
|
|
|
assert(!parmDeclType.isNull() && "GetTypeForDeclarator() returned null type");
|
|
|
|
|
2007-01-23 13:14:32 +08:00
|
|
|
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
|
|
|
|
// Can this happen for params? We already checked that they don't conflict
|
|
|
|
// among each other. Here they can only shadow globals, which is ok.
|
2008-04-08 12:40:51 +08:00
|
|
|
IdentifierInfo *II = D.getIdentifier();
|
|
|
|
if (Decl *PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, S)) {
|
2008-12-09 02:40:42 +08:00
|
|
|
if (PrevDecl->isTemplateParameter()) {
|
2008-12-06 02:15:24 +08:00
|
|
|
// Maybe we will complain about the shadowed template parameter.
|
|
|
|
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
|
|
|
|
// Just pretend that we didn't see the previous declaration.
|
|
|
|
PrevDecl = 0;
|
|
|
|
} else if (S->isDeclScope(PrevDecl)) {
|
2008-11-24 05:45:46 +08:00
|
|
|
Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II;
|
2008-04-08 12:40:51 +08:00
|
|
|
|
|
|
|
// Recover by removing the name
|
|
|
|
II = 0;
|
|
|
|
D.SetIdentifier(0, D.getIdentifierLoc());
|
|
|
|
}
|
2007-01-21 15:42:07 +08:00
|
|
|
}
|
2007-08-08 06:44:21 +08:00
|
|
|
|
|
|
|
// Perform the default function/array conversion (C99 6.7.5.3p[7,8]).
|
|
|
|
// Doing the promotion here has a win and a loss. The win is the type for
|
|
|
|
// both Decl's and DeclRefExpr's will match (a convenient invariant for the
|
|
|
|
// code generator). The loss is the orginal type isn't preserved. For example:
|
|
|
|
//
|
|
|
|
// void func(int parmvardecl[5]) { // convert "int [5]" to "int *"
|
|
|
|
// int blockvardecl[5];
|
|
|
|
// sizeof(parmvardecl); // size == 4
|
|
|
|
// sizeof(blockvardecl); // size == 20
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// For expressions, all implicit conversions are captured using the
|
|
|
|
// ImplicitCastExpr AST node (we have no such mechanism for Decl's).
|
|
|
|
//
|
|
|
|
// FIXME: If a source translation tool needs to see the original type, then
|
|
|
|
// we need to consider storing both types (in ParmVarDecl)...
|
|
|
|
//
|
2008-04-02 13:18:44 +08:00
|
|
|
if (parmDeclType->isArrayType()) {
|
2008-01-03 06:50:48 +08:00
|
|
|
// int x[restrict 4] -> int *restrict
|
2008-04-02 13:18:44 +08:00
|
|
|
parmDeclType = Context.getArrayDecayedType(parmDeclType);
|
2008-01-03 06:50:48 +08:00
|
|
|
} else if (parmDeclType->isFunctionType())
|
2007-08-08 06:44:21 +08:00
|
|
|
parmDeclType = Context.getPointerType(parmDeclType);
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
ParmVarDecl *New = ParmVarDecl::Create(Context, CurContext,
|
|
|
|
D.getIdentifierLoc(), II,
|
2008-09-04 05:54:21 +08:00
|
|
|
parmDeclType, StorageClass,
|
2008-04-08 12:40:51 +08:00
|
|
|
0, 0);
|
2008-02-15 15:04:12 +08:00
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
if (D.getInvalidType())
|
2007-08-29 02:45:29 +08:00
|
|
|
New->setInvalidDecl();
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2008-12-16 07:53:10 +08:00
|
|
|
// Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
|
|
|
|
if (D.getCXXScopeSpec().isSet()) {
|
|
|
|
Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator)
|
|
|
|
<< D.getCXXScopeSpec().getRange();
|
|
|
|
New->setInvalidDecl();
|
|
|
|
}
|
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
// Add the parameter declaration into this scope.
|
|
|
|
S->AddDecl(New);
|
2008-04-12 08:47:19 +08:00
|
|
|
if (II)
|
2008-12-12 00:49:14 +08:00
|
|
|
IdResolver.AddDecl(New);
|
2008-02-18 05:20:31 +08:00
|
|
|
|
2008-06-29 08:02:00 +08:00
|
|
|
ProcessDeclAttributes(New, D);
|
2007-01-21 15:42:07 +08:00
|
|
|
return New;
|
2008-04-08 12:40:51 +08:00
|
|
|
|
2007-01-21 15:42:07 +08:00
|
|
|
}
|
2007-11-09 07:49:49 +08:00
|
|
|
|
2007-10-10 01:14:05 +08:00
|
|
|
Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
|
2008-06-28 14:07:14 +08:00
|
|
|
assert(getCurFunctionDecl() == 0 && "Function parsing confused");
|
2006-12-03 16:41:30 +08:00
|
|
|
assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
|
|
|
|
"Not a function declarator!");
|
|
|
|
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
|
2008-04-08 12:40:51 +08:00
|
|
|
|
2006-12-03 16:41:30 +08:00
|
|
|
// Verify 6.9.1p6: 'every identifier in the identifier list shall be declared'
|
|
|
|
// for a K&R function.
|
|
|
|
if (!FTI.hasPrototype) {
|
|
|
|
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
|
2008-04-08 12:40:51 +08:00
|
|
|
if (FTI.ArgInfo[i].Param == 0) {
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)
|
|
|
|
<< FTI.ArgInfo[i].Ident;
|
2006-12-03 16:41:30 +08:00
|
|
|
// Implicitly declare the argument as type 'int' for lack of a better
|
|
|
|
// type.
|
2008-04-08 12:40:51 +08:00
|
|
|
DeclSpec DS;
|
|
|
|
const char* PrevSpec; // unused
|
|
|
|
DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
|
|
|
|
PrevSpec);
|
|
|
|
Declarator ParamD(DS, Declarator::KNRTypeListContext);
|
|
|
|
ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc);
|
|
|
|
FTI.ArgInfo[i].Param = ActOnParamDeclarator(FnBodyScope, ParamD);
|
2006-12-03 16:41:30 +08:00
|
|
|
}
|
|
|
|
}
|
2006-12-04 15:40:24 +08:00
|
|
|
} else {
|
2008-04-08 12:40:51 +08:00
|
|
|
// FIXME: Diagnose arguments without names in C.
|
2006-12-03 16:41:30 +08:00
|
|
|
}
|
|
|
|
|
2008-12-16 07:53:10 +08:00
|
|
|
Scope *ParentScope = FnBodyScope->getParent();
|
2008-01-15 04:51:29 +08:00
|
|
|
|
2008-07-01 18:37:29 +08:00
|
|
|
return ActOnStartOfFunctionDef(FnBodyScope,
|
2008-12-16 07:53:10 +08:00
|
|
|
ActOnDeclarator(ParentScope, D, 0,
|
|
|
|
/*IsFunctionDefinition=*/true));
|
2008-07-01 18:37:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
|
|
|
|
Decl *decl = static_cast<Decl*>(D);
|
2008-02-16 09:20:36 +08:00
|
|
|
FunctionDecl *FD = cast<FunctionDecl>(decl);
|
2008-10-29 23:10:40 +08:00
|
|
|
|
|
|
|
// See if this is a redefinition.
|
|
|
|
const FunctionDecl *Definition;
|
|
|
|
if (FD->getBody(Definition)) {
|
2008-11-24 05:45:46 +08:00
|
|
|
Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(Definition->getLocation(), diag::note_previous_definition);
|
2008-10-29 23:10:40 +08:00
|
|
|
}
|
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
PushDeclContext(FnBodyScope, FD);
|
2008-12-26 08:52:02 +08:00
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
// Check the validity of our function parameters
|
|
|
|
CheckParmsForFunctionDef(FD);
|
|
|
|
|
|
|
|
// Introduce our parameters into the function scope
|
|
|
|
for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
|
|
|
|
ParmVarDecl *Param = FD->getParamDecl(p);
|
|
|
|
// If this has an identifier, add it to the scope stack.
|
2008-04-12 08:47:19 +08:00
|
|
|
if (Param->getIdentifier())
|
|
|
|
PushOnScopeChains(Param, FnBodyScope);
|
2007-01-22 03:04:43 +08:00
|
|
|
}
|
2008-04-08 12:40:51 +08:00
|
|
|
|
2008-12-26 08:52:02 +08:00
|
|
|
// Checking attributes of current function definition
|
|
|
|
// dllimport attribute.
|
|
|
|
if (FD->getAttr<DLLImportAttr>() && (!FD->getAttr<DLLExportAttr>())) {
|
|
|
|
// dllimport attribute cannot be applied to definition.
|
|
|
|
if (!(FD->getAttr<DLLImportAttr>())->isInherited()) {
|
|
|
|
Diag(FD->getLocation(),
|
|
|
|
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
|
|
|
|
<< "dllimport";
|
|
|
|
FD->setInvalidDecl();
|
|
|
|
return FD;
|
|
|
|
} else {
|
|
|
|
// If a symbol previously declared dllimport is later defined, the
|
|
|
|
// attribute is ignored in subsequent references, and a warning is
|
|
|
|
// emitted.
|
|
|
|
Diag(FD->getLocation(),
|
|
|
|
diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
|
|
|
|
<< FD->getNameAsCString() << "dllimport";
|
|
|
|
}
|
|
|
|
}
|
2006-11-21 09:21:07 +08:00
|
|
|
return FD;
|
|
|
|
}
|
|
|
|
|
2008-12-14 00:23:55 +08:00
|
|
|
Sema::DeclTy *Sema::ActOnFinishFunctionBody(DeclTy *D, StmtArg BodyArg) {
|
2007-11-12 07:20:51 +08:00
|
|
|
Decl *dcl = static_cast<Decl *>(D);
|
2008-12-14 00:23:55 +08:00
|
|
|
Stmt *Body = static_cast<Stmt*>(BodyArg.release());
|
2008-07-26 01:57:26 +08:00
|
|
|
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) {
|
2008-12-14 00:23:55 +08:00
|
|
|
FD->setBody(Body);
|
2008-06-28 14:07:14 +08:00
|
|
|
assert(FD == getCurFunctionDecl() && "Function parsing confused");
|
2008-07-26 01:57:26 +08:00
|
|
|
} else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
|
2007-11-12 07:20:51 +08:00
|
|
|
MD->setBody((Stmt*)Body);
|
2008-07-26 01:57:26 +08:00
|
|
|
} else
|
|
|
|
return 0;
|
2008-04-06 12:47:34 +08:00
|
|
|
PopDeclContext();
|
2007-11-11 00:31:34 +08:00
|
|
|
// Verify and clean out per-function state.
|
|
|
|
|
|
|
|
// Check goto/label use.
|
|
|
|
for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
|
|
|
|
I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) {
|
|
|
|
// Verify that we have no forward references left. If so, there was a goto
|
|
|
|
// or address of a label taken, but no definition of it. Label fwd
|
|
|
|
// definitions are indicated with a null substmt.
|
|
|
|
if (I->second->getSubStmt() == 0) {
|
|
|
|
LabelStmt *L = I->second;
|
|
|
|
// Emit error.
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName();
|
2007-11-11 00:31:34 +08:00
|
|
|
|
|
|
|
// At this point, we have gotos that use the bogus label. Stitch it into
|
|
|
|
// the function body so that they aren't leaked and that the AST is well
|
|
|
|
// formed.
|
2008-01-25 08:01:10 +08:00
|
|
|
if (Body) {
|
|
|
|
L->setSubStmt(new NullStmt(L->getIdentLoc()));
|
2008-12-14 00:23:55 +08:00
|
|
|
cast<CompoundStmt>(Body)->push_back(L);
|
2008-01-25 08:01:10 +08:00
|
|
|
} else {
|
|
|
|
// The whole function wasn't parsed correctly, just delete this.
|
|
|
|
delete L;
|
|
|
|
}
|
2007-11-11 00:31:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
LabelMap.clear();
|
2007-11-12 07:20:51 +08:00
|
|
|
|
|
|
|
return D;
|
2007-11-11 00:31:34 +08:00
|
|
|
}
|
|
|
|
|
2006-11-20 14:49:47 +08:00
|
|
|
/// ImplicitlyDefineFunction - An undeclared identifier was used in a function
|
|
|
|
/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
|
2007-09-17 00:16:00 +08:00
|
|
|
ScopedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
|
|
|
|
IdentifierInfo &II, Scope *S) {
|
2008-05-06 05:18:06 +08:00
|
|
|
// Extension in C99. Legal in C90, but warn about it.
|
|
|
|
if (getLangOptions().C99)
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(Loc, diag::ext_implicit_function_decl) << &II;
|
2008-05-06 05:18:06 +08:00
|
|
|
else
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(Loc, diag::warn_implicit_function_decl) << &II;
|
2006-11-20 14:49:47 +08:00
|
|
|
|
|
|
|
// FIXME: handle stuff like:
|
|
|
|
// void foo() { extern float X(); }
|
|
|
|
// void bar() { X(); } <-- implicit decl for X in another scope.
|
|
|
|
|
|
|
|
// Set a Declarator for the implicit definition: int foo();
|
2006-11-28 12:50:12 +08:00
|
|
|
const char *Dummy;
|
2006-11-20 14:49:47 +08:00
|
|
|
DeclSpec DS;
|
2006-11-28 13:30:29 +08:00
|
|
|
bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy);
|
2007-02-11 16:19:57 +08:00
|
|
|
Error = Error; // Silence warning.
|
2006-11-28 12:50:12 +08:00
|
|
|
assert(!Error && "Error setting up implicit decl!");
|
2006-11-20 14:49:47 +08:00
|
|
|
Declarator D(DS, Declarator::BlockContext);
|
2008-10-25 05:46:40 +08:00
|
|
|
D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, 0, Loc));
|
2006-11-20 14:49:47 +08:00
|
|
|
D.SetIdentifier(&II, Loc);
|
|
|
|
|
2008-05-02 05:04:16 +08:00
|
|
|
// Insert this function into translation-unit scope.
|
|
|
|
|
|
|
|
DeclContext *PrevDC = CurContext;
|
|
|
|
CurContext = Context.getTranslationUnitDecl();
|
|
|
|
|
2008-04-04 22:32:09 +08:00
|
|
|
FunctionDecl *FD =
|
2008-08-06 00:28:08 +08:00
|
|
|
dyn_cast<FunctionDecl>(static_cast<Decl*>(ActOnDeclarator(TUScope, D, 0)));
|
2008-04-04 22:32:09 +08:00
|
|
|
FD->setImplicit();
|
2008-05-02 05:04:16 +08:00
|
|
|
|
|
|
|
CurContext = PrevDC;
|
|
|
|
|
2008-04-04 22:32:09 +08:00
|
|
|
return FD;
|
2006-11-20 14:49:47 +08:00
|
|
|
}
|
|
|
|
|
2006-11-19 10:31:38 +08:00
|
|
|
|
2007-11-14 14:34:38 +08:00
|
|
|
TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
|
2007-09-14 07:52:58 +08:00
|
|
|
ScopedDecl *LastDeclarator) {
|
2007-06-09 08:53:06 +08:00
|
|
|
assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
|
2007-08-29 04:14:24 +08:00
|
|
|
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
|
2006-11-20 12:34:45 +08:00
|
|
|
|
2007-01-22 15:39:13 +08:00
|
|
|
// Scope manipulation handled by caller.
|
2008-04-04 14:12:32 +08:00
|
|
|
TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
|
|
|
|
D.getIdentifierLoc(),
|
2008-03-15 14:12:44 +08:00
|
|
|
D.getIdentifier(),
|
2008-03-16 05:32:50 +08:00
|
|
|
T, LastDeclarator);
|
2007-08-29 04:14:24 +08:00
|
|
|
if (D.getInvalidType())
|
|
|
|
NewTD->setInvalidDecl();
|
|
|
|
return NewTD;
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2007-09-16 02:49:24 +08:00
|
|
|
/// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'. In the
|
2007-01-24 07:42:53 +08:00
|
|
|
/// former case, Name will be non-null. In the later case, Name will be null.
|
|
|
|
/// TagType indicates what kind of tag this is. TK indicates whether this is a
|
|
|
|
/// reference/declaration/definition of a tag.
|
2007-09-16 02:49:24 +08:00
|
|
|
Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
|
2008-11-09 00:45:02 +08:00
|
|
|
SourceLocation KWLoc, const CXXScopeSpec &SS,
|
|
|
|
IdentifierInfo *Name, SourceLocation NameLoc,
|
2008-12-24 10:52:09 +08:00
|
|
|
AttributeList *Attr,
|
|
|
|
MultiTemplateParamsArg TemplateParameterLists) {
|
2008-12-16 00:32:14 +08:00
|
|
|
// If this is not a definition, it must have a name.
|
2007-01-24 04:11:08 +08:00
|
|
|
assert((Name != 0 || TK == TK_Definition) &&
|
|
|
|
"Nameless record must be a definition!");
|
2007-01-23 09:57:16 +08:00
|
|
|
|
2008-06-10 07:19:58 +08:00
|
|
|
TagDecl::TagKind Kind;
|
2007-01-23 12:27:41 +08:00
|
|
|
switch (TagType) {
|
2007-01-23 12:08:05 +08:00
|
|
|
default: assert(0 && "Unknown tag type!");
|
2008-06-10 07:19:58 +08:00
|
|
|
case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break;
|
|
|
|
case DeclSpec::TST_union: Kind = TagDecl::TK_union; break;
|
|
|
|
case DeclSpec::TST_class: Kind = TagDecl::TK_class; break;
|
|
|
|
case DeclSpec::TST_enum: Kind = TagDecl::TK_enum; break;
|
2007-01-23 12:08:05 +08:00
|
|
|
}
|
2008-11-10 06:09:58 +08:00
|
|
|
|
2008-11-10 06:53:32 +08:00
|
|
|
DeclContext *DC = CurContext;
|
|
|
|
ScopedDecl *PrevDecl = 0;
|
2008-11-09 01:17:31 +08:00
|
|
|
|
|
|
|
if (Name && SS.isNotEmpty()) {
|
2008-11-10 06:09:58 +08:00
|
|
|
// We have a nested-name tag ('struct foo::bar').
|
|
|
|
|
|
|
|
// Check for invalid 'foo::'.
|
2008-11-10 06:53:32 +08:00
|
|
|
if (SS.isInvalid()) {
|
2008-11-09 01:17:31 +08:00
|
|
|
Name = 0;
|
|
|
|
goto CreateNewDecl;
|
|
|
|
}
|
|
|
|
|
2008-11-10 06:53:32 +08:00
|
|
|
DC = static_cast<DeclContext*>(SS.getScopeRep());
|
|
|
|
// Look-up name inside 'foo::'.
|
2008-11-10 06:09:58 +08:00
|
|
|
PrevDecl = dyn_cast_or_null<TagDecl>(LookupDecl(Name, Decl::IDNS_Tag,S,DC));
|
|
|
|
|
|
|
|
// A tag 'foo::bar' must already exist.
|
2008-11-09 01:17:31 +08:00
|
|
|
if (PrevDecl == 0) {
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange();
|
2008-11-09 01:17:31 +08:00
|
|
|
Name = 0;
|
|
|
|
goto CreateNewDecl;
|
|
|
|
}
|
2008-11-10 06:09:58 +08:00
|
|
|
} else {
|
|
|
|
// If this is a named struct, check to see if there was a previous forward
|
|
|
|
// declaration or definition.
|
|
|
|
// Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up.
|
|
|
|
PrevDecl = dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag,S));
|
2008-11-09 01:17:31 +08:00
|
|
|
}
|
|
|
|
|
2008-12-09 02:40:42 +08:00
|
|
|
if (PrevDecl && PrevDecl->isTemplateParameter()) {
|
2008-12-06 02:15:24 +08:00
|
|
|
// Maybe we will complain about the shadowed template parameter.
|
|
|
|
DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
|
|
|
|
// Just pretend that we didn't see the previous declaration.
|
|
|
|
PrevDecl = 0;
|
|
|
|
}
|
|
|
|
|
2008-09-03 05:26:19 +08:00
|
|
|
if (PrevDecl) {
|
2008-04-27 21:50:30 +08:00
|
|
|
assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) &&
|
|
|
|
"unexpected Decl type");
|
|
|
|
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
|
2008-07-03 11:30:58 +08:00
|
|
|
// If this is a use of a previous tag, or if the tag is already declared
|
|
|
|
// in the same scope (so that the definition/declaration completes or
|
2008-04-27 21:50:30 +08:00
|
|
|
// rementions the tag), reuse the decl.
|
2008-11-10 06:53:32 +08:00
|
|
|
if (TK == TK_Reference || isDeclInScope(PrevDecl, DC, S)) {
|
2008-07-03 11:30:58 +08:00
|
|
|
// Make sure that this wasn't declared as an enum and now used as a
|
|
|
|
// struct or something similar.
|
2008-06-10 07:19:58 +08:00
|
|
|
if (PrevTagDecl->getTagKind() != Kind) {
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(PrevDecl->getLocation(), diag::note_previous_use);
|
2008-07-03 11:30:58 +08:00
|
|
|
// Recover by making this an anonymous redefinition.
|
2008-04-27 21:50:30 +08:00
|
|
|
Name = 0;
|
2008-07-03 11:30:58 +08:00
|
|
|
PrevDecl = 0;
|
2008-04-27 21:50:30 +08:00
|
|
|
} else {
|
2008-12-16 00:32:14 +08:00
|
|
|
// If this is a use, just return the declaration we found.
|
2008-07-03 11:30:58 +08:00
|
|
|
|
2008-12-16 00:32:14 +08:00
|
|
|
// FIXME: In the future, return a variant or some other clue
|
|
|
|
// for the consumer of this Decl to know it doesn't own it.
|
|
|
|
// For our current ASTs this shouldn't be a problem, but will
|
|
|
|
// need to be changed with DeclGroups.
|
|
|
|
if (TK == TK_Reference)
|
|
|
|
return PrevDecl;
|
|
|
|
|
2008-07-03 11:30:58 +08:00
|
|
|
// Diagnose attempts to redefine a tag.
|
2008-12-16 00:32:14 +08:00
|
|
|
if (TK == TK_Definition) {
|
|
|
|
if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) {
|
|
|
|
Diag(NameLoc, diag::err_redefinition) << Name;
|
|
|
|
Diag(Def->getLocation(), diag::note_previous_definition);
|
|
|
|
// If this is a redefinition, recover by making this struct be
|
|
|
|
// anonymous, which will make any later references get the previous
|
|
|
|
// definition.
|
|
|
|
Name = 0;
|
|
|
|
PrevDecl = 0;
|
|
|
|
}
|
2008-07-03 11:30:58 +08:00
|
|
|
// Okay, this is definition of a previously declared or referenced
|
2008-12-16 00:32:14 +08:00
|
|
|
// tag PrevDecl. We're going to create a new Decl for it.
|
|
|
|
}
|
2008-04-27 21:50:30 +08:00
|
|
|
}
|
2008-12-16 00:32:14 +08:00
|
|
|
// If we get here we have (another) forward declaration or we
|
|
|
|
// have a definition. Just create a new decl.
|
|
|
|
} else {
|
|
|
|
// If we get here, this is a definition of a new tag type in a nested
|
|
|
|
// scope, e.g. "struct foo; void bar() { struct foo; }", just create a
|
|
|
|
// new decl/type. We set PrevDecl to NULL so that the entities
|
|
|
|
// have distinct types.
|
|
|
|
PrevDecl = 0;
|
2007-01-24 04:11:08 +08:00
|
|
|
}
|
2008-12-16 00:32:14 +08:00
|
|
|
// If we get here, we're going to create a new Decl. If PrevDecl
|
|
|
|
// is non-NULL, it's a definition of the tag declared by
|
|
|
|
// PrevDecl. If it's NULL, we have a new definition.
|
2008-04-27 21:50:30 +08:00
|
|
|
} else {
|
2008-07-16 15:45:46 +08:00
|
|
|
// PrevDecl is a namespace.
|
2008-11-10 06:53:32 +08:00
|
|
|
if (isDeclInScope(PrevDecl, DC, S)) {
|
2008-09-04 02:03:35 +08:00
|
|
|
// The tag name clashes with a namespace name, issue an error and
|
|
|
|
// recover by making this tag be anonymous.
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
2008-07-16 15:45:46 +08:00
|
|
|
Name = 0;
|
2008-12-16 00:32:14 +08:00
|
|
|
PrevDecl = 0;
|
|
|
|
} else {
|
|
|
|
// The existing declaration isn't relevant to us; we're in a
|
|
|
|
// new scope, so clear out the previous declaration.
|
|
|
|
PrevDecl = 0;
|
2008-07-16 15:45:46 +08:00
|
|
|
}
|
2007-01-23 09:57:16 +08:00
|
|
|
}
|
2007-01-22 15:39:13 +08:00
|
|
|
}
|
2008-11-09 01:17:31 +08:00
|
|
|
|
2008-12-17 15:13:27 +08:00
|
|
|
CreateNewDecl:
|
2007-01-22 15:39:13 +08:00
|
|
|
|
2007-01-23 12:27:41 +08:00
|
|
|
// If there is an identifier, use the location of the identifier as the
|
|
|
|
// location of the decl, otherwise use the location of the struct/union
|
|
|
|
// keyword.
|
|
|
|
SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc;
|
|
|
|
|
2008-12-16 00:32:14 +08:00
|
|
|
// Otherwise, create a new declaration. If there is a previous
|
|
|
|
// declaration of the same entity, the two will be linked via
|
|
|
|
// PrevDecl.
|
2007-01-24 04:11:08 +08:00
|
|
|
TagDecl *New;
|
2008-06-10 07:19:58 +08:00
|
|
|
if (Kind == TagDecl::TK_enum) {
|
2007-06-09 08:53:06 +08:00
|
|
|
// FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
|
|
|
|
// enum X { A, B, C } D; D should chain to X.
|
2008-12-16 00:32:14 +08:00
|
|
|
New = EnumDecl::Create(Context, DC, Loc, Name,
|
|
|
|
cast_or_null<EnumDecl>(PrevDecl));
|
2007-01-25 14:27:24 +08:00
|
|
|
// If this is an undefined enum, warn.
|
2007-01-25 15:29:02 +08:00
|
|
|
if (TK != TK_Definition) Diag(Loc, diag::ext_forward_ref_enum);
|
2008-06-10 07:19:58 +08:00
|
|
|
} else {
|
|
|
|
// struct/union/class
|
|
|
|
|
2007-06-09 08:53:06 +08:00
|
|
|
// FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
|
|
|
|
// struct X { int A; } D; D should chain to X.
|
2008-07-01 18:37:29 +08:00
|
|
|
if (getLangOptions().CPlusPlus)
|
2008-09-06 01:39:33 +08:00
|
|
|
// FIXME: Look for a way to use RecordDecl for simple structs.
|
2008-12-16 00:32:14 +08:00
|
|
|
New = CXXRecordDecl::Create(Context, Kind, DC, Loc, Name,
|
|
|
|
cast_or_null<CXXRecordDecl>(PrevDecl));
|
2008-07-01 18:37:29 +08:00
|
|
|
else
|
2008-12-16 00:32:14 +08:00
|
|
|
New = RecordDecl::Create(Context, Kind, DC, Loc, Name,
|
|
|
|
cast_or_null<RecordDecl>(PrevDecl));
|
2008-07-01 18:37:29 +08:00
|
|
|
}
|
2008-12-16 00:32:14 +08:00
|
|
|
|
|
|
|
if (Kind != TagDecl::TK_enum) {
|
|
|
|
// Handle #pragma pack: if the #pragma pack stack has non-default
|
|
|
|
// alignment, make up a packed attribute for this decl. These
|
|
|
|
// attributes are checked when the ASTContext lays out the
|
|
|
|
// structure.
|
|
|
|
//
|
|
|
|
// It is important for implementing the correct semantics that this
|
|
|
|
// happen here (in act on tag decl). The #pragma pack stack is
|
|
|
|
// maintained as a result of parser callbacks which can occur at
|
|
|
|
// many points during the parsing of a struct declaration (because
|
|
|
|
// the #pragma tokens are effectively skipped over during the
|
|
|
|
// parsing of the struct).
|
|
|
|
if (unsigned Alignment = PackContext.getAlignment())
|
|
|
|
New->addAttr(new PackedAttr(Alignment * 8));
|
2007-01-22 15:39:13 +08:00
|
|
|
}
|
2008-12-16 00:32:14 +08:00
|
|
|
|
2008-06-29 07:58:55 +08:00
|
|
|
if (Attr)
|
|
|
|
ProcessDeclAttributeList(New, Attr);
|
2008-11-10 07:41:00 +08:00
|
|
|
|
|
|
|
// Set the lexical context. If the tag has a C++ scope specifier, the
|
|
|
|
// lexical context will be different from the semantic context.
|
|
|
|
New->setLexicalDeclContext(CurContext);
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
|
|
|
|
// If this has an identifier, add it to the scope stack.
|
2008-12-16 00:32:14 +08:00
|
|
|
if (Name) {
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
// The scope passed in may not be a decl scope. Zip up the scope tree until
|
|
|
|
// we find one that is.
|
|
|
|
while ((S->getFlags() & Scope::DeclScope) == 0)
|
|
|
|
S = S->getParent();
|
|
|
|
|
|
|
|
// Add it to the decl chain.
|
|
|
|
PushOnScopeChains(New, S);
|
|
|
|
}
|
2008-10-16 10:34:03 +08:00
|
|
|
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
2008-06-22 03:39:06 +08:00
|
|
|
|
2008-11-13 05:17:48 +08:00
|
|
|
/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
|
|
|
|
/// types into constant array types in certain situations which would otherwise
|
|
|
|
/// be errors (for GCC compatibility).
|
|
|
|
static QualType TryToFixInvalidVariablyModifiedType(QualType T,
|
|
|
|
ASTContext &Context) {
|
2008-06-04 05:01:11 +08:00
|
|
|
// This method tries to turn a variable array into a constant
|
|
|
|
// array even when the size isn't an ICE. This is necessary
|
|
|
|
// for compatibility with code that depends on gcc's buggy
|
|
|
|
// constant expression folding, like struct {char x[(int)(char*)2];}
|
2008-11-13 03:48:13 +08:00
|
|
|
const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
|
|
|
|
if (!VLATy) return QualType();
|
|
|
|
|
2008-12-20 04:58:05 +08:00
|
|
|
Expr::EvalResult EvalResult;
|
2008-11-13 03:48:13 +08:00
|
|
|
if (!VLATy->getSizeExpr() ||
|
2008-12-20 04:58:05 +08:00
|
|
|
!VLATy->getSizeExpr()->Evaluate(EvalResult, Context))
|
2008-11-13 03:48:13 +08:00
|
|
|
return QualType();
|
|
|
|
|
2008-12-20 04:58:05 +08:00
|
|
|
assert(EvalResult.Val.isInt() && "Size expressions must be integers!");
|
|
|
|
llvm::APSInt &Res = EvalResult.Val.getInt();
|
2008-11-13 03:48:13 +08:00
|
|
|
if (Res > llvm::APSInt(Res.getBitWidth(), Res.isUnsigned()))
|
|
|
|
return Context.getConstantArrayType(VLATy->getElementType(),
|
|
|
|
Res, ArrayType::Normal, 0);
|
2008-06-04 05:01:11 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2008-12-07 04:33:04 +08:00
|
|
|
bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
|
2008-12-12 12:56:04 +08:00
|
|
|
QualType FieldTy, const Expr *BitWidth) {
|
2008-12-07 04:33:04 +08:00
|
|
|
// FIXME: 6.7.2.1p4 - verify the field type.
|
|
|
|
|
|
|
|
llvm::APSInt Value;
|
|
|
|
if (VerifyIntegerConstantExpression(BitWidth, &Value))
|
|
|
|
return true;
|
|
|
|
|
2008-12-12 12:56:04 +08:00
|
|
|
// Zero-width bitfield is ok for anonymous field.
|
|
|
|
if (Value == 0 && FieldName)
|
|
|
|
return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName;
|
|
|
|
|
|
|
|
if (Value.isNegative())
|
|
|
|
return Diag(FieldLoc, diag::err_bitfield_has_negative_width) << FieldName;
|
2008-12-07 04:33:04 +08:00
|
|
|
|
|
|
|
uint64_t TypeSize = Context.getTypeSize(FieldTy);
|
|
|
|
// FIXME: We won't need the 0 size once we check that the field type is valid.
|
2008-12-12 12:56:04 +08:00
|
|
|
if (TypeSize && Value.getZExtValue() > TypeSize)
|
|
|
|
return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size)
|
|
|
|
<< FieldName << (unsigned)TypeSize;
|
2008-12-07 04:33:04 +08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-09-16 02:49:24 +08:00
|
|
|
/// ActOnField - Each field of a struct/union/class is passed into this in order
|
2007-01-24 07:42:53 +08:00
|
|
|
/// to create a FieldDecl object for it.
|
2008-12-12 00:49:14 +08:00
|
|
|
Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
|
2007-01-24 07:42:53 +08:00
|
|
|
SourceLocation DeclStart,
|
|
|
|
Declarator &D, ExprTy *BitfieldWidth) {
|
|
|
|
IdentifierInfo *II = D.getIdentifier();
|
|
|
|
Expr *BitWidth = (Expr*)BitfieldWidth;
|
|
|
|
SourceLocation Loc = DeclStart;
|
2008-12-12 00:49:14 +08:00
|
|
|
RecordDecl *Record = (RecordDecl *)TagD;
|
2007-01-24 07:42:53 +08:00
|
|
|
if (II) Loc = D.getIdentifierLoc();
|
|
|
|
|
2007-01-28 08:21:37 +08:00
|
|
|
// FIXME: Unnamed fields can be handled in various different ways, for
|
|
|
|
// example, unnamed unions inject all members into the struct namespace!
|
2007-01-24 07:42:53 +08:00
|
|
|
|
2007-04-06 06:36:20 +08:00
|
|
|
QualType T = GetTypeForDeclarator(D, S);
|
2007-08-29 04:14:24 +08:00
|
|
|
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
|
|
|
|
bool InvalidDecl = false;
|
2008-12-07 04:33:04 +08:00
|
|
|
|
2007-05-09 05:09:37 +08:00
|
|
|
// C99 6.7.2.1p8: A member of a structure or union may have any type other
|
|
|
|
// than a variably modified type.
|
2008-02-15 20:53:51 +08:00
|
|
|
if (T->isVariablyModifiedType()) {
|
2008-11-13 05:17:48 +08:00
|
|
|
QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context);
|
2008-06-04 05:01:11 +08:00
|
|
|
if (!FixedTy.isNull()) {
|
2008-11-14 02:49:38 +08:00
|
|
|
Diag(Loc, diag::warn_illegal_constant_array_size);
|
2008-06-04 05:01:11 +08:00
|
|
|
T = FixedTy;
|
|
|
|
} else {
|
2008-11-14 02:49:38 +08:00
|
|
|
Diag(Loc, diag::err_typecheck_field_variable_size);
|
2008-11-13 03:45:49 +08:00
|
|
|
T = Context.IntTy;
|
2008-06-04 05:01:11 +08:00
|
|
|
InvalidDecl = true;
|
|
|
|
}
|
2007-05-09 05:09:37 +08:00
|
|
|
}
|
2008-12-07 04:33:04 +08:00
|
|
|
|
|
|
|
if (BitWidth) {
|
|
|
|
if (VerifyBitField(Loc, II, T, BitWidth))
|
|
|
|
InvalidDecl = true;
|
|
|
|
} else {
|
|
|
|
// Not a bitfield.
|
|
|
|
|
|
|
|
// validate II.
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2007-06-09 08:53:06 +08:00
|
|
|
// FIXME: Chain fielddecls together.
|
2008-07-01 18:37:29 +08:00
|
|
|
FieldDecl *NewFD;
|
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
// FIXME: We don't want CurContext for C, do we? No, we'll need some
|
|
|
|
// other way to determine the current RecordDecl.
|
|
|
|
NewFD = FieldDecl::Create(Context, Record,
|
|
|
|
Loc, II, T, BitWidth,
|
|
|
|
D.getDeclSpec().getStorageClassSpec() ==
|
|
|
|
DeclSpec::SCS_mutable,
|
|
|
|
/*PrevDecl=*/0);
|
|
|
|
|
2008-12-17 05:30:33 +08:00
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
CheckExtraCXXDefaultArguments(D);
|
|
|
|
|
2008-06-29 08:02:00 +08:00
|
|
|
ProcessDeclAttributes(NewFD, D);
|
2008-02-16 08:29:18 +08:00
|
|
|
|
2007-08-29 04:14:24 +08:00
|
|
|
if (D.getInvalidType() || InvalidDecl)
|
|
|
|
NewFD->setInvalidDecl();
|
2008-12-12 00:49:14 +08:00
|
|
|
|
|
|
|
if (II && getLangOptions().CPlusPlus)
|
|
|
|
PushOnScopeChains(NewFD, S);
|
|
|
|
else
|
|
|
|
Record->addDecl(Context, NewFD);
|
|
|
|
|
2007-08-29 04:14:24 +08:00
|
|
|
return NewFD;
|
2007-01-24 07:42:53 +08:00
|
|
|
}
|
|
|
|
|
2007-10-02 00:53:59 +08:00
|
|
|
/// TranslateIvarVisibility - Translate visibility from a token ID to an
|
|
|
|
/// AST enum value.
|
2008-01-08 03:49:32 +08:00
|
|
|
static ObjCIvarDecl::AccessControl
|
2007-10-02 00:53:59 +08:00
|
|
|
TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
|
2007-09-15 07:09:53 +08:00
|
|
|
switch (ivarVisibility) {
|
2008-10-12 08:28:42 +08:00
|
|
|
default: assert(0 && "Unknown visitibility kind");
|
|
|
|
case tok::objc_private: return ObjCIvarDecl::Private;
|
|
|
|
case tok::objc_public: return ObjCIvarDecl::Public;
|
|
|
|
case tok::objc_protected: return ObjCIvarDecl::Protected;
|
|
|
|
case tok::objc_package: return ObjCIvarDecl::Package;
|
2007-09-15 07:09:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-12 00:55:42 +08:00
|
|
|
/// ActOnIvar - Each ivar field of an objective-c class is passed into this
|
|
|
|
/// in order to create an IvarDecl object for it.
|
2008-04-11 07:32:45 +08:00
|
|
|
Sema::DeclTy *Sema::ActOnIvar(Scope *S,
|
2008-04-12 00:55:42 +08:00
|
|
|
SourceLocation DeclStart,
|
|
|
|
Declarator &D, ExprTy *BitfieldWidth,
|
|
|
|
tok::ObjCKeywordKind Visibility) {
|
2008-04-11 07:32:45 +08:00
|
|
|
IdentifierInfo *II = D.getIdentifier();
|
|
|
|
Expr *BitWidth = (Expr*)BitfieldWidth;
|
|
|
|
SourceLocation Loc = DeclStart;
|
|
|
|
if (II) Loc = D.getIdentifierLoc();
|
|
|
|
|
|
|
|
// FIXME: Unnamed fields can be handled in various different ways, for
|
|
|
|
// example, unnamed unions inject all members into the struct namespace!
|
|
|
|
|
2008-12-07 04:33:04 +08:00
|
|
|
QualType T = GetTypeForDeclarator(D, S);
|
|
|
|
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
|
|
|
|
bool InvalidDecl = false;
|
2008-04-11 07:32:45 +08:00
|
|
|
|
|
|
|
if (BitWidth) {
|
|
|
|
// TODO: Validate.
|
|
|
|
//printf("WARNING: BITFIELDS IGNORED!\n");
|
|
|
|
|
|
|
|
// 6.7.2.1p3
|
|
|
|
// 6.7.2.1p4
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// Not a bitfield.
|
|
|
|
|
|
|
|
// validate II.
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// C99 6.7.2.1p8: A member of a structure or union may have any type other
|
|
|
|
// than a variably modified type.
|
|
|
|
if (T->isVariablyModifiedType()) {
|
2008-12-07 08:20:55 +08:00
|
|
|
Diag(Loc, diag::err_typecheck_ivar_variable_size);
|
2008-04-11 07:32:45 +08:00
|
|
|
InvalidDecl = true;
|
|
|
|
}
|
|
|
|
|
2008-07-24 02:04:17 +08:00
|
|
|
// Get the visibility (access control) for this ivar.
|
|
|
|
ObjCIvarDecl::AccessControl ac =
|
|
|
|
Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
|
|
|
|
: ObjCIvarDecl::None;
|
|
|
|
|
|
|
|
// Construct the decl.
|
|
|
|
ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, Loc, II, T, ac,
|
2008-07-17 02:22:22 +08:00
|
|
|
(Expr *)BitfieldWidth);
|
2008-04-11 07:32:45 +08:00
|
|
|
|
2008-07-24 02:04:17 +08:00
|
|
|
// Process attributes attached to the ivar.
|
2008-06-29 08:02:00 +08:00
|
|
|
ProcessDeclAttributes(NewID, D);
|
2008-04-11 07:32:45 +08:00
|
|
|
|
|
|
|
if (D.getInvalidType() || InvalidDecl)
|
|
|
|
NewID->setInvalidDecl();
|
2008-07-24 02:04:17 +08:00
|
|
|
|
2008-04-11 07:32:45 +08:00
|
|
|
return NewID;
|
|
|
|
}
|
|
|
|
|
2007-09-29 08:54:24 +08:00
|
|
|
void Sema::ActOnFields(Scope* S,
|
2007-10-04 08:45:27 +08:00
|
|
|
SourceLocation RecLoc, DeclTy *RecDecl,
|
2007-09-16 02:49:24 +08:00
|
|
|
DeclTy **Fields, unsigned NumFields,
|
2008-10-03 10:03:53 +08:00
|
|
|
SourceLocation LBrac, SourceLocation RBrac,
|
2008-10-04 01:33:35 +08:00
|
|
|
AttributeList *Attr) {
|
2007-09-15 06:20:54 +08:00
|
|
|
Decl *EnclosingDecl = static_cast<Decl*>(RecDecl);
|
|
|
|
assert(EnclosingDecl && "missing record or interface decl");
|
|
|
|
RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
|
|
|
|
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
if (Record)
|
|
|
|
if (RecordDecl* DefRecord = Record->getDefinition(Context)) {
|
|
|
|
// Diagnose code like:
|
|
|
|
// struct S { struct S {} X; };
|
|
|
|
// We discover this when we complete the outer S. Reject and ignore the
|
|
|
|
// outer S.
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(DefRecord->getLocation(), diag::err_nested_redefinition)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< DefRecord->getDeclName();
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(RecLoc, diag::note_previous_definition);
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
Record->setInvalidDecl();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-01-24 10:11:17 +08:00
|
|
|
// Verify that all the fields are okay.
|
2007-01-24 10:26:21 +08:00
|
|
|
unsigned NumNamedMembers = 0;
|
2007-06-16 07:05:46 +08:00
|
|
|
llvm::SmallVector<FieldDecl*, 32> RecFields;
|
|
|
|
llvm::SmallSet<const IdentifierInfo*, 32> FieldIDs;
|
2007-09-15 06:20:54 +08:00
|
|
|
|
2007-01-24 10:11:17 +08:00
|
|
|
for (unsigned i = 0; i != NumFields; ++i) {
|
2007-09-15 00:27:55 +08:00
|
|
|
|
2007-09-15 06:20:54 +08:00
|
|
|
FieldDecl *FD = cast_or_null<FieldDecl>(static_cast<Decl*>(Fields[i]));
|
|
|
|
assert(FD && "missing field decl");
|
|
|
|
|
|
|
|
// Remember all fields.
|
|
|
|
RecFields.push_back(FD);
|
2007-01-25 08:44:24 +08:00
|
|
|
|
|
|
|
// Get the type for the field.
|
2007-08-01 05:33:24 +08:00
|
|
|
Type *FDTy = FD->getType().getTypePtr();
|
2007-09-15 07:09:53 +08:00
|
|
|
|
2007-01-24 10:11:17 +08:00
|
|
|
// C99 6.7.2.1p2 - A field may not be a function type.
|
2007-08-01 05:33:24 +08:00
|
|
|
if (FDTy->isFunctionType()) {
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(FD->getLocation(), diag::err_field_declared_as_function)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< FD->getDeclName();
|
2007-09-15 06:20:54 +08:00
|
|
|
FD->setInvalidDecl();
|
|
|
|
EnclosingDecl->setInvalidDecl();
|
2007-01-24 10:11:17 +08:00
|
|
|
continue;
|
|
|
|
}
|
2007-01-24 10:26:21 +08:00
|
|
|
// C99 6.7.2.1p2 - A field may not be an incomplete type except...
|
2007-01-25 08:44:24 +08:00
|
|
|
if (FDTy->isIncompleteType()) {
|
2007-09-15 00:27:55 +08:00
|
|
|
if (!Record) { // Incomplete ivar type is always an error.
|
2008-11-24 13:29:24 +08:00
|
|
|
Diag(FD->getLocation(), diag::err_field_incomplete) <<FD->getDeclName();
|
2007-09-15 06:20:54 +08:00
|
|
|
FD->setInvalidDecl();
|
|
|
|
EnclosingDecl->setInvalidDecl();
|
2007-10-04 08:45:27 +08:00
|
|
|
continue;
|
2007-09-15 00:27:55 +08:00
|
|
|
}
|
2007-01-24 10:26:21 +08:00
|
|
|
if (i != NumFields-1 || // ... that the last member ...
|
2008-06-10 07:19:58 +08:00
|
|
|
!Record->isStruct() || // ... of a structure ...
|
2007-08-01 05:33:24 +08:00
|
|
|
!FDTy->isArrayType()) { //... may have incomplete array type.
|
2008-11-24 13:29:24 +08:00
|
|
|
Diag(FD->getLocation(), diag::err_field_incomplete) <<FD->getDeclName();
|
2007-09-15 06:20:54 +08:00
|
|
|
FD->setInvalidDecl();
|
|
|
|
EnclosingDecl->setInvalidDecl();
|
2007-01-24 10:26:21 +08:00
|
|
|
continue;
|
|
|
|
}
|
2007-09-15 00:27:55 +08:00
|
|
|
if (NumNamedMembers < 1) { //... must have more than named member ...
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(FD->getLocation(), diag::err_flexible_array_empty_struct)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< FD->getDeclName();
|
2007-09-15 06:20:54 +08:00
|
|
|
FD->setInvalidDecl();
|
|
|
|
EnclosingDecl->setInvalidDecl();
|
2007-01-24 10:26:21 +08:00
|
|
|
continue;
|
|
|
|
}
|
2007-01-25 08:44:24 +08:00
|
|
|
// Okay, we have a legal flexible array member at the end of the struct.
|
2007-09-15 00:27:55 +08:00
|
|
|
if (Record)
|
|
|
|
Record->setHasFlexibleArrayMember(true);
|
2007-01-25 08:44:24 +08:00
|
|
|
}
|
|
|
|
/// C99 6.7.2.1p2 - a struct ending in a flexible array member cannot be the
|
|
|
|
/// field of another structure or the element of an array.
|
2007-08-01 05:33:24 +08:00
|
|
|
if (const RecordType *FDTTy = FDTy->getAsRecordType()) {
|
2007-01-25 08:44:24 +08:00
|
|
|
if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
|
|
|
|
// If this is a member of a union, then entire union becomes "flexible".
|
2008-06-10 07:19:58 +08:00
|
|
|
if (Record && Record->isUnion()) {
|
2007-01-25 12:52:46 +08:00
|
|
|
Record->setHasFlexibleArrayMember(true);
|
2007-01-25 08:44:24 +08:00
|
|
|
} else {
|
|
|
|
// If this is a struct/class and this is not the last element, reject
|
|
|
|
// it. Note that GCC supports variable sized arrays in the middle of
|
|
|
|
// structures.
|
|
|
|
if (i != NumFields-1) {
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(FD->getLocation(), diag::err_variable_sized_type_in_struct)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< FD->getDeclName();
|
2007-09-15 06:20:54 +08:00
|
|
|
FD->setInvalidDecl();
|
|
|
|
EnclosingDecl->setInvalidDecl();
|
2007-01-25 08:44:24 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// We support flexible arrays at the end of structs in other structs
|
|
|
|
// as an extension.
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(FD->getLocation(), diag::ext_flexible_array_in_struct)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< FD->getDeclName();
|
2007-10-04 08:45:27 +08:00
|
|
|
if (Record)
|
2007-09-15 00:27:55 +08:00
|
|
|
Record->setHasFlexibleArrayMember(true);
|
2007-01-25 08:44:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-10-13 06:10:42 +08:00
|
|
|
/// A field cannot be an Objective-c object
|
2008-01-08 03:49:32 +08:00
|
|
|
if (FDTy->isObjCInterfaceType()) {
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(FD->getLocation(), diag::err_statically_allocated_object)
|
2008-11-24 05:45:46 +08:00
|
|
|
<< FD->getDeclName();
|
2007-10-13 06:10:42 +08:00
|
|
|
FD->setInvalidDecl();
|
|
|
|
EnclosingDecl->setInvalidDecl();
|
|
|
|
continue;
|
|
|
|
}
|
2007-01-24 10:26:21 +08:00
|
|
|
// Keep track of the number of named members.
|
2007-01-26 06:48:42 +08:00
|
|
|
if (IdentifierInfo *II = FD->getIdentifier()) {
|
|
|
|
// Detect duplicate member names.
|
2007-01-27 10:14:08 +08:00
|
|
|
if (!FieldIDs.insert(II)) {
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(FD->getLocation(), diag::err_duplicate_member) << II;
|
2007-01-26 06:48:42 +08:00
|
|
|
// Find the previous decl.
|
|
|
|
SourceLocation PrevLoc;
|
2008-10-12 08:28:42 +08:00
|
|
|
for (unsigned i = 0; ; ++i) {
|
|
|
|
assert(i != RecFields.size() && "Didn't find previous def!");
|
2007-01-26 06:48:42 +08:00
|
|
|
if (RecFields[i]->getIdentifier() == II) {
|
|
|
|
PrevLoc = RecFields[i]->getLocation();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(PrevLoc, diag::note_previous_definition);
|
2007-09-15 06:20:54 +08:00
|
|
|
FD->setInvalidDecl();
|
|
|
|
EnclosingDecl->setInvalidDecl();
|
2007-01-26 06:48:42 +08:00
|
|
|
continue;
|
|
|
|
}
|
2007-01-24 10:26:21 +08:00
|
|
|
++NumNamedMembers;
|
2007-01-26 06:48:42 +08:00
|
|
|
}
|
2007-01-24 10:11:17 +08:00
|
|
|
}
|
2007-01-24 10:26:21 +08:00
|
|
|
|
|
|
|
// Okay, we successfully defined 'Record'.
|
2008-02-06 08:51:33 +08:00
|
|
|
if (Record) {
|
2008-12-12 00:49:14 +08:00
|
|
|
Record->completeDefinition(Context);
|
2008-08-09 08:58:37 +08:00
|
|
|
// If this is a C++ record, HandleTagDeclDefinition will be invoked in
|
|
|
|
// Sema::ActOnFinishCXXClassDef.
|
|
|
|
if (!isa<CXXRecordDecl>(Record))
|
|
|
|
Consumer.HandleTagDeclDefinition(Record);
|
2008-02-06 08:51:33 +08:00
|
|
|
} else {
|
2008-02-06 06:40:55 +08:00
|
|
|
ObjCIvarDecl **ClsFields = reinterpret_cast<ObjCIvarDecl**>(&RecFields[0]);
|
2008-12-14 04:28:25 +08:00
|
|
|
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl)) {
|
2008-02-06 06:40:55 +08:00
|
|
|
ID->addInstanceVariablesToClass(ClsFields, RecFields.size(), RBrac);
|
2008-12-16 09:08:35 +08:00
|
|
|
// Must enforce the rule that ivars in the base classes may not be
|
|
|
|
// duplicates.
|
2008-12-18 06:21:44 +08:00
|
|
|
if (ID->getSuperClass()) {
|
|
|
|
for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(),
|
|
|
|
IVE = ID->ivar_end(); IVI != IVE; ++IVI) {
|
|
|
|
ObjCIvarDecl* Ivar = (*IVI);
|
|
|
|
IdentifierInfo *II = Ivar->getIdentifier();
|
|
|
|
ObjCIvarDecl* prevIvar = ID->getSuperClass()->FindIvarDeclaration(II);
|
|
|
|
if (prevIvar) {
|
|
|
|
Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;
|
|
|
|
Diag(prevIvar->getLocation(), diag::note_previous_definition);
|
2008-12-16 09:08:35 +08:00
|
|
|
}
|
2008-12-18 06:21:44 +08:00
|
|
|
}
|
2008-12-16 09:08:35 +08:00
|
|
|
}
|
2008-12-14 04:28:25 +08:00
|
|
|
}
|
2008-02-06 06:40:55 +08:00
|
|
|
else if (ObjCImplementationDecl *IMPDecl =
|
|
|
|
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
|
2008-01-08 03:49:32 +08:00
|
|
|
assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl");
|
|
|
|
IMPDecl->ObjCAddInstanceVariablesToClassImpl(ClsFields, RecFields.size());
|
2007-11-01 02:48:14 +08:00
|
|
|
CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac);
|
2007-09-27 02:27:25 +08:00
|
|
|
}
|
2007-09-15 05:08:27 +08:00
|
|
|
}
|
2008-10-04 01:33:35 +08:00
|
|
|
|
|
|
|
if (Attr)
|
|
|
|
ProcessDeclAttributeList(Record, Attr);
|
2007-01-24 07:42:53 +08:00
|
|
|
}
|
|
|
|
|
2007-09-16 02:49:24 +08:00
|
|
|
Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
|
2007-06-11 09:28:17 +08:00
|
|
|
DeclTy *lastEnumConst,
|
2007-01-25 15:29:02 +08:00
|
|
|
SourceLocation IdLoc, IdentifierInfo *Id,
|
2007-06-11 09:28:17 +08:00
|
|
|
SourceLocation EqualLoc, ExprTy *val) {
|
2008-04-04 14:12:32 +08:00
|
|
|
EnumDecl *TheEnumDecl = cast<EnumDecl>(static_cast<Decl*>(theEnumDecl));
|
2007-06-11 09:28:17 +08:00
|
|
|
EnumConstantDecl *LastEnumConst =
|
|
|
|
cast_or_null<EnumConstantDecl>(static_cast<Decl*>(lastEnumConst));
|
|
|
|
Expr *Val = static_cast<Expr*>(val);
|
2007-01-26 06:38:29 +08:00
|
|
|
|
2007-08-26 14:24:45 +08:00
|
|
|
// The scope passed in may not be a decl scope. Zip up the scope tree until
|
|
|
|
// we find one that is.
|
|
|
|
while ((S->getFlags() & Scope::DeclScope) == 0)
|
|
|
|
S = S->getParent();
|
|
|
|
|
2007-01-26 06:38:29 +08:00
|
|
|
// Verify that there isn't already something declared with this name in this
|
|
|
|
// scope.
|
2008-12-06 02:15:24 +08:00
|
|
|
Decl *PrevDecl = LookupDecl(Id, Decl::IDNS_Ordinary, S);
|
2008-12-09 02:40:42 +08:00
|
|
|
if (PrevDecl && PrevDecl->isTemplateParameter()) {
|
2008-12-06 02:15:24 +08:00
|
|
|
// Maybe we will complain about the shadowed template parameter.
|
|
|
|
DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
|
|
|
|
// Just pretend that we didn't see the previous declaration.
|
|
|
|
PrevDecl = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PrevDecl) {
|
2008-07-17 05:01:53 +08:00
|
|
|
// When in C++, we may get a TagDecl with the same name; in this case the
|
|
|
|
// enum constant will 'hide' the tag.
|
|
|
|
assert((getLangOptions().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
|
|
|
|
"Received TagDecl when not in C++!");
|
2008-09-10 05:18:04 +08:00
|
|
|
if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) {
|
2007-01-26 06:38:29 +08:00
|
|
|
if (isa<EnumConstantDecl>(PrevDecl))
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
|
2007-01-26 06:38:29 +08:00
|
|
|
else
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(IdLoc, diag::err_redefinition) << Id;
|
2008-11-24 07:12:31 +08:00
|
|
|
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
2008-02-26 08:33:57 +08:00
|
|
|
delete Val;
|
2007-01-26 06:38:29 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2007-06-11 09:28:17 +08:00
|
|
|
|
2007-06-16 07:05:46 +08:00
|
|
|
llvm::APSInt EnumVal(32);
|
2007-06-11 09:28:17 +08:00
|
|
|
QualType EltTy;
|
|
|
|
if (Val) {
|
2007-08-28 05:16:18 +08:00
|
|
|
// Make sure to promote the operand type to int.
|
|
|
|
UsualUnaryConversions(Val);
|
|
|
|
|
2007-06-11 09:28:17 +08:00
|
|
|
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
|
|
|
|
SourceLocation ExpLoc;
|
2008-12-06 00:33:57 +08:00
|
|
|
if (VerifyIntegerConstantExpression(Val, &EnumVal)) {
|
2008-02-26 08:33:57 +08:00
|
|
|
delete Val;
|
2007-08-28 01:37:24 +08:00
|
|
|
Val = 0; // Just forget about it.
|
2007-08-30 00:03:41 +08:00
|
|
|
} else {
|
|
|
|
EltTy = Val->getType();
|
2007-06-11 09:28:17 +08:00
|
|
|
}
|
2007-08-28 01:37:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!Val) {
|
|
|
|
if (LastEnumConst) {
|
|
|
|
// Assign the last value + 1.
|
|
|
|
EnumVal = LastEnumConst->getInitVal();
|
|
|
|
++EnumVal;
|
2007-08-28 05:16:18 +08:00
|
|
|
|
|
|
|
// Check for overflow on increment.
|
|
|
|
if (EnumVal < LastEnumConst->getInitVal())
|
|
|
|
Diag(IdLoc, diag::warn_enum_value_overflow);
|
|
|
|
|
2007-08-28 01:37:24 +08:00
|
|
|
EltTy = LastEnumConst->getType();
|
|
|
|
} else {
|
|
|
|
// First value, set to zero.
|
|
|
|
EltTy = Context.IntTy;
|
2008-03-06 02:54:05 +08:00
|
|
|
EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy)));
|
2007-08-28 01:37:24 +08:00
|
|
|
}
|
2007-05-08 05:22:42 +08:00
|
|
|
}
|
2007-06-11 09:28:17 +08:00
|
|
|
|
2008-03-15 14:12:44 +08:00
|
|
|
EnumConstantDecl *New =
|
2008-04-04 14:12:32 +08:00
|
|
|
EnumConstantDecl::Create(Context, TheEnumDecl, IdLoc, Id, EltTy,
|
|
|
|
Val, EnumVal,
|
2008-03-16 05:32:50 +08:00
|
|
|
LastEnumConst);
|
2007-01-26 06:38:29 +08:00
|
|
|
|
|
|
|
// Register this decl in the current scope stack.
|
2008-04-12 08:47:19 +08:00
|
|
|
PushOnScopeChains(New, S);
|
2008-12-17 10:04:30 +08:00
|
|
|
|
|
|
|
// Add this enumerator into the enum itself.
|
|
|
|
// FIXME: This means that the enumerator is stored in two
|
|
|
|
// DeclContexts. This is not a long-term solution.
|
|
|
|
New->setLexicalDeclContext(TheEnumDecl);
|
|
|
|
TheEnumDecl->addDecl(Context, New, true);
|
2007-01-26 06:38:29 +08:00
|
|
|
return New;
|
2007-01-25 15:29:02 +08:00
|
|
|
}
|
|
|
|
|
2008-08-07 22:08:16 +08:00
|
|
|
// FIXME: For consistency with ActOnFields(), we should have the parser
|
|
|
|
// pass in the source location for the left/right braces.
|
2007-09-16 02:49:24 +08:00
|
|
|
void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
|
2007-01-25 15:29:02 +08:00
|
|
|
DeclTy **Elements, unsigned NumElements) {
|
|
|
|
EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
|
|
|
|
|
2008-12-16 00:32:14 +08:00
|
|
|
if (Enum) {
|
|
|
|
if (EnumDecl *Def = cast_or_null<EnumDecl>(Enum->getDefinition(Context))) {
|
|
|
|
// Diagnose code like:
|
|
|
|
// enum e0 {
|
|
|
|
// E0 = sizeof(enum e0 { E1 })
|
|
|
|
// };
|
|
|
|
Diag(Def->getLocation(), diag::err_nested_redefinition)
|
|
|
|
<< Enum->getDeclName();
|
|
|
|
Diag(Enum->getLocation(), diag::note_previous_definition);
|
|
|
|
Enum->setInvalidDecl();
|
|
|
|
return;
|
|
|
|
}
|
2008-08-07 22:08:16 +08:00
|
|
|
}
|
2007-08-28 13:10:31 +08:00
|
|
|
// TODO: If the result value doesn't fit in an int, it must be a long or long
|
|
|
|
// long value. ISO C does not support this, but GCC does as an extension,
|
|
|
|
// emit a warning.
|
2008-03-06 02:54:05 +08:00
|
|
|
unsigned IntWidth = Context.Target.getIntWidth();
|
2007-08-28 13:10:31 +08:00
|
|
|
|
2007-08-28 14:15:15 +08:00
|
|
|
// Verify that all the values are okay, compute the size of the values, and
|
|
|
|
// reverse the list.
|
|
|
|
unsigned NumNegativeBits = 0;
|
|
|
|
unsigned NumPositiveBits = 0;
|
|
|
|
|
|
|
|
// Keep track of whether all elements have type int.
|
|
|
|
bool AllElementsInt = true;
|
|
|
|
|
2008-12-12 10:00:36 +08:00
|
|
|
QualType EnumType = Context.getTypeDeclType(Enum);
|
2007-06-11 09:28:17 +08:00
|
|
|
EnumConstantDecl *EltList = 0;
|
2007-01-25 15:29:02 +08:00
|
|
|
for (unsigned i = 0; i != NumElements; ++i) {
|
|
|
|
EnumConstantDecl *ECD =
|
|
|
|
cast_or_null<EnumConstantDecl>(static_cast<Decl*>(Elements[i]));
|
|
|
|
if (!ECD) continue; // Already issued a diagnostic.
|
2007-08-28 13:27:00 +08:00
|
|
|
|
|
|
|
// If the enum value doesn't fit in an int, emit an extension warning.
|
|
|
|
const llvm::APSInt &InitVal = ECD->getInitVal();
|
2008-02-26 08:33:57 +08:00
|
|
|
assert(InitVal.getBitWidth() >= IntWidth &&
|
|
|
|
"Should have promoted value to int");
|
2007-08-28 13:27:00 +08:00
|
|
|
if (InitVal.getBitWidth() > IntWidth) {
|
|
|
|
llvm::APSInt V(InitVal);
|
|
|
|
V.trunc(IntWidth);
|
|
|
|
V.extend(InitVal.getBitWidth());
|
|
|
|
if (V != InitVal)
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(ECD->getLocation(), diag::ext_enum_value_not_int)
|
|
|
|
<< InitVal.toString(10);
|
2007-08-28 13:27:00 +08:00
|
|
|
}
|
2007-08-28 14:15:15 +08:00
|
|
|
|
|
|
|
// Keep track of the size of positive and negative values.
|
2008-02-26 08:33:57 +08:00
|
|
|
if (InitVal.isUnsigned() || InitVal.isNonNegative())
|
2008-01-15 05:47:29 +08:00
|
|
|
NumPositiveBits = std::max(NumPositiveBits,
|
|
|
|
(unsigned)InitVal.getActiveBits());
|
2007-08-28 14:15:15 +08:00
|
|
|
else
|
2008-01-15 05:47:29 +08:00
|
|
|
NumNegativeBits = std::max(NumNegativeBits,
|
|
|
|
(unsigned)InitVal.getMinSignedBits());
|
2007-06-11 09:28:17 +08:00
|
|
|
|
2007-08-28 14:15:15 +08:00
|
|
|
// Keep track of whether every enum element has type int (very commmon).
|
|
|
|
if (AllElementsInt)
|
|
|
|
AllElementsInt = ECD->getType() == Context.IntTy;
|
|
|
|
|
2007-06-11 09:28:17 +08:00
|
|
|
ECD->setNextDeclarator(EltList);
|
|
|
|
EltList = ECD;
|
2007-01-25 15:29:02 +08:00
|
|
|
}
|
|
|
|
|
2007-08-28 14:15:15 +08:00
|
|
|
// Figure out the type that should be used for this enum.
|
|
|
|
// FIXME: Support attribute(packed) on enums and -fshort-enums.
|
|
|
|
QualType BestType;
|
2007-08-30 01:31:48 +08:00
|
|
|
unsigned BestWidth;
|
2007-08-28 14:15:15 +08:00
|
|
|
|
|
|
|
if (NumNegativeBits) {
|
|
|
|
// If there is a negative value, figure out the smallest integer type (of
|
|
|
|
// int/long/longlong) that fits.
|
2007-08-30 01:31:48 +08:00
|
|
|
if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
|
2007-08-28 14:15:15 +08:00
|
|
|
BestType = Context.IntTy;
|
2007-08-30 01:31:48 +08:00
|
|
|
BestWidth = IntWidth;
|
|
|
|
} else {
|
2008-03-06 02:54:05 +08:00
|
|
|
BestWidth = Context.Target.getLongWidth();
|
2007-12-13 06:39:36 +08:00
|
|
|
|
2007-08-30 01:31:48 +08:00
|
|
|
if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth)
|
2007-08-28 14:15:15 +08:00
|
|
|
BestType = Context.LongTy;
|
|
|
|
else {
|
2008-03-06 02:54:05 +08:00
|
|
|
BestWidth = Context.Target.getLongLongWidth();
|
2007-12-13 06:39:36 +08:00
|
|
|
|
2007-08-30 01:31:48 +08:00
|
|
|
if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
|
2007-08-28 14:15:15 +08:00
|
|
|
Diag(Enum->getLocation(), diag::warn_enum_too_large);
|
|
|
|
BestType = Context.LongLongTy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// If there is no negative value, figure out which of uint, ulong, ulonglong
|
|
|
|
// fits.
|
2007-08-30 01:31:48 +08:00
|
|
|
if (NumPositiveBits <= IntWidth) {
|
2007-08-28 14:15:15 +08:00
|
|
|
BestType = Context.UnsignedIntTy;
|
2007-08-30 01:31:48 +08:00
|
|
|
BestWidth = IntWidth;
|
|
|
|
} else if (NumPositiveBits <=
|
2008-03-06 02:54:05 +08:00
|
|
|
(BestWidth = Context.Target.getLongWidth())) {
|
2007-08-28 14:15:15 +08:00
|
|
|
BestType = Context.UnsignedLongTy;
|
2008-03-06 02:54:05 +08:00
|
|
|
} else {
|
|
|
|
BestWidth = Context.Target.getLongLongWidth();
|
2007-08-30 01:31:48 +08:00
|
|
|
assert(NumPositiveBits <= BestWidth &&
|
2007-08-28 14:15:15 +08:00
|
|
|
"How could an initializer get larger than ULL?");
|
|
|
|
BestType = Context.UnsignedLongLongTy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-30 01:31:48 +08:00
|
|
|
// Loop over all of the enumerator constants, changing their types to match
|
|
|
|
// the type of the enum if needed.
|
|
|
|
for (unsigned i = 0; i != NumElements; ++i) {
|
|
|
|
EnumConstantDecl *ECD =
|
|
|
|
cast_or_null<EnumConstantDecl>(static_cast<Decl*>(Elements[i]));
|
|
|
|
if (!ECD) continue; // Already issued a diagnostic.
|
|
|
|
|
|
|
|
// Standard C says the enumerators have int type, but we allow, as an
|
|
|
|
// extension, the enumerators to be larger than int size. If each
|
|
|
|
// enumerator value fits in an int, type it as an int, otherwise type it the
|
|
|
|
// same as the enumerator decl itself. This means that in "enum { X = 1U }"
|
|
|
|
// that X has type 'int', not 'unsigned'.
|
2008-02-26 08:33:57 +08:00
|
|
|
if (ECD->getType() == Context.IntTy) {
|
|
|
|
// Make sure the init value is signed.
|
|
|
|
llvm::APSInt IV = ECD->getInitVal();
|
|
|
|
IV.setIsSigned(true);
|
|
|
|
ECD->setInitVal(IV);
|
2008-12-12 10:00:36 +08:00
|
|
|
|
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
// C++ [dcl.enum]p4: Following the closing brace of an
|
|
|
|
// enum-specifier, each enumerator has the type of its
|
|
|
|
// enumeration.
|
|
|
|
ECD->setType(EnumType);
|
2007-08-30 01:31:48 +08:00
|
|
|
continue; // Already int type.
|
2008-02-26 08:33:57 +08:00
|
|
|
}
|
2007-08-30 01:31:48 +08:00
|
|
|
|
|
|
|
// Determine whether the value fits into an int.
|
|
|
|
llvm::APSInt InitVal = ECD->getInitVal();
|
|
|
|
bool FitsInInt;
|
|
|
|
if (InitVal.isUnsigned() || !InitVal.isNegative())
|
|
|
|
FitsInInt = InitVal.getActiveBits() < IntWidth;
|
|
|
|
else
|
|
|
|
FitsInInt = InitVal.getMinSignedBits() <= IntWidth;
|
|
|
|
|
|
|
|
// If it fits into an integer type, force it. Otherwise force it to match
|
|
|
|
// the enum decl type.
|
|
|
|
QualType NewTy;
|
|
|
|
unsigned NewWidth;
|
|
|
|
bool NewSign;
|
|
|
|
if (FitsInInt) {
|
|
|
|
NewTy = Context.IntTy;
|
|
|
|
NewWidth = IntWidth;
|
|
|
|
NewSign = true;
|
|
|
|
} else if (ECD->getType() == BestType) {
|
|
|
|
// Already the right type!
|
2008-12-12 10:00:36 +08:00
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
// C++ [dcl.enum]p4: Following the closing brace of an
|
|
|
|
// enum-specifier, each enumerator has the type of its
|
|
|
|
// enumeration.
|
|
|
|
ECD->setType(EnumType);
|
2007-08-30 01:31:48 +08:00
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
NewTy = BestType;
|
|
|
|
NewWidth = BestWidth;
|
|
|
|
NewSign = BestType->isSignedIntegerType();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust the APSInt value.
|
|
|
|
InitVal.extOrTrunc(NewWidth);
|
|
|
|
InitVal.setIsSigned(NewSign);
|
|
|
|
ECD->setInitVal(InitVal);
|
|
|
|
|
|
|
|
// Adjust the Expr initializer and type.
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
ECD->setInitExpr(new ImplicitCastExpr(NewTy, ECD->getInitExpr(),
|
|
|
|
/*isLvalue=*/false));
|
2008-12-12 10:00:36 +08:00
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
// C++ [dcl.enum]p4: Following the closing brace of an
|
|
|
|
// enum-specifier, each enumerator has the type of its
|
|
|
|
// enumeration.
|
|
|
|
ECD->setType(EnumType);
|
|
|
|
else
|
|
|
|
ECD->setType(NewTy);
|
2007-08-30 01:31:48 +08:00
|
|
|
}
|
2007-08-28 14:15:15 +08:00
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
Enum->completeDefinition(Context, BestType);
|
2008-02-06 08:51:33 +08:00
|
|
|
Consumer.HandleTagDeclDefinition(Enum);
|
2007-01-25 15:29:02 +08:00
|
|
|
}
|
2007-01-24 07:42:53 +08:00
|
|
|
|
2008-02-08 08:33:21 +08:00
|
|
|
Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc,
|
2008-12-14 00:23:55 +08:00
|
|
|
ExprArg expr) {
|
|
|
|
StringLiteral *AsmString = cast<StringLiteral>((Expr*)expr.release());
|
|
|
|
|
2008-03-16 08:16:02 +08:00
|
|
|
return FileScopeAsmDecl::Create(Context, Loc, AsmString);
|
2008-02-08 08:33:21 +08:00
|
|
|
}
|
|
|
|
|
2008-12-17 06:23:02 +08:00
|
|
|
|
2008-10-14 13:35:18 +08:00
|
|
|
void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
|
|
|
|
ExprTy *alignment, SourceLocation PragmaLoc,
|
|
|
|
SourceLocation LParenLoc, SourceLocation RParenLoc) {
|
|
|
|
Expr *Alignment = static_cast<Expr *>(alignment);
|
|
|
|
|
|
|
|
// If specified then alignment must be a "small" power of two.
|
|
|
|
unsigned AlignmentVal = 0;
|
|
|
|
if (Alignment) {
|
|
|
|
llvm::APSInt Val;
|
|
|
|
if (!Alignment->isIntegerConstantExpr(Val, Context) ||
|
|
|
|
!Val.isPowerOf2() ||
|
|
|
|
Val.getZExtValue() > 16) {
|
|
|
|
Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
|
|
|
|
delete Alignment;
|
|
|
|
return; // Ignore
|
|
|
|
}
|
|
|
|
|
|
|
|
AlignmentVal = (unsigned) Val.getZExtValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (Kind) {
|
|
|
|
case Action::PPK_Default: // pack([n])
|
|
|
|
PackContext.setAlignment(AlignmentVal);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Action::PPK_Show: // pack(show)
|
|
|
|
// Show the current alignment, making sure to show the right value
|
|
|
|
// for the default.
|
|
|
|
AlignmentVal = PackContext.getAlignment();
|
|
|
|
// FIXME: This should come from the target.
|
|
|
|
if (AlignmentVal == 0)
|
|
|
|
AlignmentVal = 8;
|
2008-11-19 15:25:44 +08:00
|
|
|
Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
|
2008-10-14 13:35:18 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Action::PPK_Push: // pack(push [, id] [, [n])
|
|
|
|
PackContext.push(Name);
|
|
|
|
// Set the new alignment if specified.
|
|
|
|
if (Alignment)
|
|
|
|
PackContext.setAlignment(AlignmentVal);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Action::PPK_Pop: // pack(pop [, id] [, n])
|
|
|
|
// MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
|
|
|
|
// "#pragma pack(pop, identifier, n) is undefined"
|
|
|
|
if (Alignment && Name)
|
|
|
|
Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
|
|
|
|
|
|
|
|
// Do the pop.
|
|
|
|
if (!PackContext.pop(Name)) {
|
|
|
|
// If a name was specified then failure indicates the name
|
|
|
|
// wasn't found. Otherwise failure indicates the stack was
|
|
|
|
// empty.
|
2008-11-20 14:38:18 +08:00
|
|
|
Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
|
|
|
|
<< (Name ? "no record matching name" : "stack empty");
|
2008-10-14 13:35:18 +08:00
|
|
|
|
|
|
|
// FIXME: Warn about popping named records as MSVC does.
|
|
|
|
} else {
|
|
|
|
// Pop succeeded, set the new alignment if specified.
|
|
|
|
if (Alignment)
|
|
|
|
PackContext.setAlignment(AlignmentVal);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(0 && "Invalid #pragma pack kind.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PragmaPackStack::pop(IdentifierInfo *Name) {
|
|
|
|
if (Stack.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// If name is empty just pop top.
|
|
|
|
if (!Name) {
|
|
|
|
Alignment = Stack.back().first;
|
|
|
|
Stack.pop_back();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, find the named record.
|
|
|
|
for (unsigned i = Stack.size(); i != 0; ) {
|
|
|
|
--i;
|
2008-11-19 18:32:38 +08:00
|
|
|
if (Stack[i].second == Name) {
|
2008-10-14 13:35:18 +08:00
|
|
|
// Found it, pop up to and including this record.
|
|
|
|
Alignment = Stack[i].first;
|
|
|
|
Stack.erase(Stack.begin() + i, Stack.end());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|