aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-03-15 23:59:48 +0000
committerChris Lattner <sabre@nondot.org>2008-03-15 23:59:48 +0000
commitbda0b626e74513950405c27525af87e214e605e2 (patch)
tree60149b18fd68ccc1281c62fe4387b5a1da39a5fa /lib/Sema/SemaDecl.cpp
parentfbdeba1c530dc3534a6f5b788e43d1a43c260128 (diff)
Make a major restructuring of the clang tree: introduce a top-level
lib dir and move all the libraries into it. This follows the main llvm tree, and allows the libraries to be built in parallel. The top level now enforces that all the libs are built before Driver, but we don't care what order the libs are built in. This speeds up parallel builds, particularly incremental ones. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@48402 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp2297
1 files changed, 2297 insertions, 0 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
new file mode 100644
index 0000000000..7914e86574
--- /dev/null
+++ b/lib/Sema/SemaDecl.cpp
@@ -0,0 +1,2297 @@
+//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Builtins.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/SourceManager.h"
+// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/DenseSet.h"
+using namespace clang;
+
+Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
+ Decl *IIDecl = II.getFETokenInfo<Decl>();
+ // Find first occurance of none-tagged declaration
+ while(IIDecl && IIDecl->getIdentifierNamespace() != Decl::IDNS_Ordinary)
+ IIDecl = cast<ScopedDecl>(IIDecl)->getNext();
+ if (!IIDecl)
+ return 0;
+ if (isa<TypedefDecl>(IIDecl) || isa<ObjCInterfaceDecl>(IIDecl))
+ return IIDecl;
+ if (ObjCCompatibleAliasDecl *ADecl =
+ dyn_cast<ObjCCompatibleAliasDecl>(IIDecl))
+ return ADecl->getClassInterface();
+ return 0;
+}
+
+void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
+ if (S->decl_empty()) return;
+ assert((S->getFlags() & Scope::DeclScope) &&"Scope shouldn't contain decls!");
+
+ for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
+ I != E; ++I) {
+ Decl *TmpD = static_cast<Decl*>(*I);
+ assert(TmpD && "This decl didn't get pushed??");
+ ScopedDecl *D = dyn_cast<ScopedDecl>(TmpD);
+ assert(D && "This decl isn't a ScopedDecl?");
+
+ IdentifierInfo *II = D->getIdentifier();
+ if (!II) continue;
+
+ // Unlink this decl from the identifier. Because the scope contains decls
+ // in an unordered collection, and because we have multiple identifier
+ // namespaces (e.g. tag, normal, label),the decl may not be the first entry.
+ if (II->getFETokenInfo<Decl>() == D) {
+ // Normal case, no multiple decls in different namespaces.
+ II->setFETokenInfo(D->getNext());
+ } else {
+ // Scan ahead. There are only three namespaces in C, so this loop can
+ // never execute more than 3 times.
+ ScopedDecl *SomeDecl = II->getFETokenInfo<ScopedDecl>();
+ while (SomeDecl->getNext() != D) {
+ SomeDecl = SomeDecl->getNext();
+ assert(SomeDecl && "Didn't find this decl on its identifier's chain!");
+ }
+ SomeDecl->setNext(D->getNext());
+ }
+
+ // This will have to be revisited for C++: there we want to nest stuff in
+ // namespace decls etc. Even for C, we might want a top-level translation
+ // unit decl or something.
+ if (!CurFunctionDecl)
+ continue;
+
+ // Chain this decl to the containing function, it now owns the memory for
+ // the decl.
+ D->setNext(CurFunctionDecl->getDeclChain());
+ CurFunctionDecl->setDeclChain(D);
+ }
+}
+
+/// LookupInterfaceDecl - Lookup interface declaration in the scope chain.
+/// Return the first declaration found (which may or may not be a class
+/// declaration. Caller is responsible for handling the none-class case.
+/// Bypassing the alias of a class by returning the aliased class.
+ScopedDecl *Sema::LookupInterfaceDecl(IdentifierInfo *ClassName) {
+ ScopedDecl *IDecl;
+ // Scan up the scope chain looking for a decl that matches this identifier
+ // that is in the appropriate namespace.
+ for (IDecl = ClassName->getFETokenInfo<ScopedDecl>(); IDecl;
+ IDecl = IDecl->getNext())
+ if (IDecl->getIdentifierNamespace() == Decl::IDNS_Ordinary)
+ break;
+
+ if (ObjCCompatibleAliasDecl *ADecl =
+ dyn_cast_or_null<ObjCCompatibleAliasDecl>(IDecl))
+ return ADecl->getClassInterface();
+ return IDecl;
+}
+
+/// getObjCInterfaceDecl - Look up a for a class declaration in the scope.
+/// return 0 if one not found.
+ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
+ ScopedDecl *IdDecl = LookupInterfaceDecl(Id);
+ return cast_or_null<ObjCInterfaceDecl>(IdDecl);
+}
+
+/// LookupScopedDecl - Look up the inner-most declaration in the specified
+/// namespace.
+ScopedDecl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
+ SourceLocation IdLoc, Scope *S) {
+ if (II == 0) return 0;
+ Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
+
+ // 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 (ScopedDecl *D = II->getFETokenInfo<ScopedDecl>(); D; D = D->getNext())
+ if (D->getIdentifierNamespace() == NS)
+ return D;
+
+ // 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.
+ if (NS == Decl::IDNS_Ordinary) {
+ // If this is a builtin on this (or all) targets, create the decl.
+ if (unsigned BuiltinID = II->getBuiltinID())
+ return LazilyCreateBuiltin(II, BuiltinID, S);
+ }
+ return 0;
+}
+
+void Sema::InitBuiltinVaListType()
+{
+ if (!Context.getBuiltinVaListType().isNull())
+ return;
+
+ IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list");
+ ScopedDecl *VaDecl = LookupScopedDecl(VaIdent, Decl::IDNS_Ordinary,
+ SourceLocation(), TUScope);
+ TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl);
+ Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef));
+}
+
+/// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope.
+/// lazily create a decl for it.
+ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
+ Scope *S) {
+ Builtin::ID BID = (Builtin::ID)bid;
+
+ if (BID == Builtin::BI__builtin_va_start ||
+ BID == Builtin::BI__builtin_va_copy ||
+ BID == Builtin::BI__builtin_va_end)
+ InitBuiltinVaListType();
+
+ QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context);
+ FunctionDecl *New = FunctionDecl::Create(Context, SourceLocation(), II, R,
+ FunctionDecl::Extern, false, 0);
+
+ // Find translation-unit scope to insert this function into.
+ if (Scope *FnS = S->getFnParent())
+ S = FnS->getParent(); // Skip all scopes in a function at once.
+ while (S->getParent())
+ S = S->getParent();
+ S->AddDecl(New);
+
+ // Add this decl to the end of the identifier info.
+ if (ScopedDecl *LastDecl = II->getFETokenInfo<ScopedDecl>()) {
+ // Scan until we find the last (outermost) decl in the id chain.
+ while (LastDecl->getNext())
+ LastDecl = LastDecl->getNext();
+ // Insert before (outside) it.
+ LastDecl->setNext(New);
+ } else {
+ II->setFETokenInfo(New);
+ }
+ return New;
+}
+
+/// 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.
+///
+TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, ScopedDecl *OldD) {
+ // Verify the old decl was also a typedef.
+ TypedefDecl *Old = dyn_cast<TypedefDecl>(OldD);
+ if (!Old) {
+ Diag(New->getLocation(), diag::err_redefinition_different_kind,
+ New->getName());
+ Diag(OldD->getLocation(), diag::err_previous_definition);
+ return New;
+ }
+
+ // Allow multiple definitions for ObjC built-in typedefs.
+ // FIXME: Verify the underlying types are equivalent!
+ if (getLangOptions().ObjC1 && isBuiltinObjCType(New))
+ return Old;
+
+ // Redeclaration of a type is a constraint violation (6.7.2.3p1).
+ // 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).
+ SourceManager &SrcMgr = Context.getSourceManager();
+ const FileEntry *OldDeclFile = SrcMgr.getFileEntryForLoc(Old->getLocation());
+ const FileEntry *NewDeclFile = SrcMgr.getFileEntryForLoc(New->getLocation());
+ HeaderSearch &HdrInfo = PP.getHeaderSearchInfo();
+ DirectoryLookup::DirType OldDirType = HdrInfo.getFileDirFlavor(OldDeclFile);
+ DirectoryLookup::DirType NewDirType = HdrInfo.getFileDirFlavor(NewDeclFile);
+
+ if ((OldDirType == DirectoryLookup::ExternCSystemHeaderDir ||
+ NewDirType == DirectoryLookup::ExternCSystemHeaderDir) ||
+ getLangOptions().Microsoft)
+ return New;
+
+ // 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; ...
+ Diag(New->getLocation(), diag::err_redefinition, New->getName());
+ Diag(Old->getLocation(), diag::err_previous_definition);
+ return New;
+}
+
+/// DeclhasAttr - returns true if decl Declaration already has the target attribute.
+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;
+
+// FIXME: fix this code to cleanup the Old attrs correctly
+ while (attr) {
+ tmp = attr;
+ attr = attr->getNext();
+
+ if (!DeclHasAttr(New, tmp)) {
+ New->addAttr(tmp);
+ } else {
+ tmp->setNext(0);
+ delete(tmp);
+ }
+ }
+}
+
+/// MergeFunctionDecl - We just parsed a function '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.
+///
+FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, ScopedDecl *OldD) {
+ // Verify the old decl was also a function.
+ FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD);
+ if (!Old) {
+ Diag(New->getLocation(), diag::err_redefinition_different_kind,
+ New->getName());
+ Diag(OldD->getLocation(), diag::err_previous_definition);
+ return New;
+ }
+
+ MergeAttributes(New, Old);
+
+
+ QualType OldQType = Old->getCanonicalType();
+ QualType NewQType = New->getCanonicalType();
+
+ // Function types need to be compatible, not identical. This handles
+ // duplicate function decls like "void f(int); void f(enum X);" properly.
+ if (Context.functionTypesAreCompatible(OldQType, NewQType))
+ return New;
+
+ // A function that has already been declared has been redeclared or defined
+ // with a different type- show appropriate diagnostic
+ diag::kind PrevDiag = Old->getBody() ? diag::err_previous_definition :
+ diag::err_previous_declaration;
+
+ // 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; ...
+ Diag(New->getLocation(), diag::err_conflicting_types, New->getName());
+ Diag(Old->getLocation(), PrevDiag);
+ return New;
+}
+
+/// equivalentArrayTypes - Used to determine whether two array types are
+/// equivalent.
+/// We need to check this explicitly as an incomplete array definition is
+/// considered a VariableArrayType, so will not match a complete array
+/// definition that would be otherwise equivalent.
+static bool areEquivalentArrayTypes(QualType NewQType, QualType OldQType) {
+ const ArrayType *NewAT = NewQType->getAsArrayType();
+ const ArrayType *OldAT = OldQType->getAsArrayType();
+
+ if (!NewAT || !OldAT)
+ return false;
+
+ // If either (or both) array types in incomplete we need to strip off the
+ // outer VariableArrayType. Once the outer VAT is removed the remaining
+ // types must be identical if the array types are to be considered
+ // equivalent.
+ // eg. int[][1] and int[1][1] become
+ // VAT(null, CAT(1, int)) and CAT(1, CAT(1, int))
+ // removing the outermost VAT gives
+ // CAT(1, int) and CAT(1, int)
+ // which are equal, therefore the array types are equivalent.
+ if (NewAT->isIncompleteArrayType() || OldAT->isIncompleteArrayType()) {
+ if (NewAT->getIndexTypeQualifier() != OldAT->getIndexTypeQualifier())
+ return false;
+ NewQType = NewAT->getElementType().getCanonicalType();
+ OldQType = OldAT->getElementType().getCanonicalType();
+ }
+
+ return NewQType == OldQType;
+}
+
+/// 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.
+///
+/// FIXME: Need to carefully consider tentative definition rules (C99 6.9.2p2).
+/// For example, we incorrectly complain about i1, i4 from C99 6.9.2p4.
+///
+VarDecl *Sema::MergeVarDecl(VarDecl *New, ScopedDecl *OldD) {
+ // Verify the old decl was also a variable.
+ VarDecl *Old = dyn_cast<VarDecl>(OldD);
+ if (!Old) {
+ Diag(New->getLocation(), diag::err_redefinition_different_kind,
+ New->getName());
+ Diag(OldD->getLocation(), diag::err_previous_definition);
+ return New;
+ }
+
+ MergeAttributes(New, Old);
+
+ // Verify the types match.
+ if (Old->getCanonicalType() != New->getCanonicalType() &&
+ !areEquivalentArrayTypes(New->getCanonicalType(), Old->getCanonicalType())) {
+ Diag(New->getLocation(), diag::err_redefinition, New->getName());
+ Diag(Old->getLocation(), diag::err_previous_definition);
+ 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)) {
+ Diag(New->getLocation(), diag::err_static_non_static, New->getName());
+ Diag(Old->getLocation(), diag::err_previous_definition);
+ 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) {
+ Diag(New->getLocation(), diag::err_non_static_static, New->getName());
+ Diag(Old->getLocation(), diag::err_previous_definition);
+ return New;
+ }
+ // We've verified the types match, now handle "tentative" definitions.
+ FileVarDecl *OldFSDecl = dyn_cast<FileVarDecl>(Old);
+ FileVarDecl *NewFSDecl = dyn_cast<FileVarDecl>(New);
+
+ if (OldFSDecl && NewFSDecl) {
+ // Handle C "tentative" external object definitions (C99 6.9.2).
+ bool OldIsTentative = false;
+ bool NewIsTentative = false;
+
+ if (!OldFSDecl->getInit() &&
+ (OldFSDecl->getStorageClass() == VarDecl::None ||
+ OldFSDecl->getStorageClass() == VarDecl::Static))
+ OldIsTentative = true;
+
+ // FIXME: this check doesn't work (since the initializer hasn't been
+ // attached yet). This check should be moved to FinalizeDeclaratorGroup.
+ // Unfortunately, by the time we get to FinializeDeclaratorGroup, we've
+ // thrown out the old decl.
+ if (!NewFSDecl->getInit() &&
+ (NewFSDecl->getStorageClass() == VarDecl::None ||
+ NewFSDecl->getStorageClass() == VarDecl::Static))
+ ; // change to NewIsTentative = true; once the code is moved.
+
+ if (NewIsTentative || OldIsTentative)
+ return New;
+ }
+ if (Old->getStorageClass() != VarDecl::Extern &&
+ New->getStorageClass() != VarDecl::Extern) {
+ Diag(New->getLocation(), diag::err_redefinition, New->getName());
+ Diag(Old->getLocation(), diag::err_previous_definition);
+ }
+ return New;
+}
+
+/// 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) {
+ // TODO: emit error on 'int;' or 'const enum foo;'.
+ // TODO: emit error on 'typedef int;'
+ // if (!DS.isMissingDeclaratorOk()) Diag(...);
+
+ return dyn_cast_or_null<TagDecl>(static_cast<Decl *>(DS.getTypeRep()));
+}
+
+bool Sema::CheckSingleInitializer(Expr *&Init, QualType DeclType) {
+ // Get the type before calling CheckSingleAssignmentConstraints(), since
+ // it can promote the expression.
+ QualType InitType = Init->getType();
+
+ AssignConvertType ConvTy = CheckSingleAssignmentConstraints(DeclType, Init);
+ return DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
+ InitType, Init, "initializing");
+}
+
+bool Sema::CheckInitExpr(Expr *expr, InitListExpr *IList, unsigned slot,
+ QualType ElementType) {
+ Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer.
+ if (CheckSingleInitializer(expr, ElementType))
+ return true; // types weren't compatible.
+
+ if (savExpr != expr) // The type was promoted, update initializer list.
+ IList->setInit(slot, expr);
+ return false;
+}
+
+bool Sema::CheckStringLiteralInit(StringLiteral *strLiteral, QualType &DeclT) {
+ if (const IncompleteArrayType *IAT = DeclT->getAsIncompleteArrayType()) {
+ // 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).
+ DeclT = Context.getConstantArrayType(IAT->getElementType(), ConstVal,
+ ArrayType::Normal, 0);
+ } else if (const ConstantArrayType *CAT = DeclT->getAsConstantArrayType()) {
+ // C99 6.7.8p14. We have an array of character type with known size.
+ if (strLiteral->getByteLength() > (unsigned)CAT->getMaximumElements())
+ Diag(strLiteral->getSourceRange().getBegin(),
+ diag::warn_initializer_string_for_char_array_too_long,
+ strLiteral->getSourceRange());
+ } else {
+ assert(0 && "HandleStringLiteralInit(): Invalid array type");
+ }
+ // 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) {
+ const ArrayType *AT = DeclType->getAsArrayType();
+ if (AT && AT->getElementType()->isCharType()) {
+ return dyn_cast<StringLiteral>(Init);
+ }
+ return 0;
+}
+
+// CheckInitializerListTypes - Checks the types of elements of an initializer
+// list. This function is recursive: it calls itself to initialize subelements
+// of aggregate types. Note that the topLevel parameter essentially refers to
+// whether this expression "owns" the initializer list passed in, or if this
+// initialization is taking elements out of a parent initializer. Each
+// call to this function adds zero or more to startIndex, reports any errors,
+// and returns true if it found any inconsistent types.
+bool Sema::CheckInitializerListTypes(InitListExpr*& IList, QualType &DeclType,
+ bool topLevel, unsigned& startIndex) {
+ bool hadError = false;
+
+ if (DeclType->isScalarType()) {
+ // The simplest case: initializing a single scalar
+ if (topLevel) {
+ Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init,
+ IList->getSourceRange());
+ }
+ if (startIndex < IList->getNumInits()) {
+ Expr* expr = IList->getInit(startIndex);
+ if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+ // FIXME: Should an error be reported here instead?
+ unsigned newIndex = 0;
+ CheckInitializerListTypes(SubInitList, DeclType, true, newIndex);
+ } else {
+ hadError |= CheckInitExpr(expr, IList, startIndex, DeclType);
+ }
+ ++startIndex;
+ }
+ // FIXME: Should an error be reported for empty initializer list + scalar?
+ } else if (DeclType->isVectorType()) {
+ if (startIndex < IList->getNumInits()) {
+ const VectorType *VT = DeclType->getAsVectorType();
+ int maxElements = VT->getNumElements();
+ QualType elementType = VT->getElementType();
+
+ for (int i = 0; i < maxElements; ++i) {
+ // Don't attempt to go past the end of the init list
+ if (startIndex >= IList->getNumInits())
+ break;
+ Expr* expr = IList->getInit(startIndex);
+ if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+ unsigned newIndex = 0;
+ hadError |= CheckInitializerListTypes(SubInitList, elementType,
+ true, newIndex);
+ ++startIndex;
+ } else {
+ hadError |= CheckInitializerListTypes(IList, elementType,
+ false, startIndex);
+ }
+ }
+ }
+ } else if (DeclType->isAggregateType() || DeclType->isUnionType()) {
+ if (DeclType->isStructureType() || DeclType->isUnionType()) {
+ if (startIndex < IList->getNumInits() && !topLevel &&
+ Context.typesAreCompatible(IList->getInit(startIndex)->getType(),
+ DeclType)) {
+ // We found a compatible struct; per the standard, this initializes the
+ // struct. (The C standard technically says that this only applies for
+ // initializers for declarations with automatic scope; however, this
+ // construct is unambiguous anyway because a struct cannot contain
+ // a type compatible with itself. We'll output an error when we check
+ // if the initializer is constant.)
+ // FIXME: Is a call to CheckSingleInitializer required here?
+ ++startIndex;
+ } else {
+ RecordDecl* structDecl = DeclType->getAsRecordType()->getDecl();
+
+ // If the record is invalid, some of it's members are invalid. To avoid
+ // confusion, we forgo checking the intializer for the entire record.
+ if (structDecl->isInvalidDecl())
+ return true;
+
+ // If structDecl is a forward declaration, this loop won't do anything;
+ // That's okay, because an error should get printed out elsewhere. It
+ // might be worthwhile to skip over the rest of the initializer, though.
+ int numMembers = structDecl->getNumMembers() -
+ structDecl->hasFlexibleArrayMember();
+ for (int i = 0; i < numMembers; i++) {
+ // Don't attempt to go past the end of the init list
+ if (startIndex >= IList->getNumInits())
+ break;
+ FieldDecl * curField = structDecl->getMember(i);
+ if (!curField->getIdentifier()) {
+ // Don't initialize unnamed fields, e.g. "int : 20;"
+ continue;
+ }
+ QualType fieldType = curField->getType();
+ Expr* expr = IList->getInit(startIndex);
+ if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+ unsigned newStart = 0;
+ hadError |= CheckInitializerListTypes(SubInitList, fieldType,
+ true, newStart);
+ ++startIndex;
+ } else {
+ hadError |= CheckInitializerListTypes(IList, fieldType,
+ false, startIndex);
+ }
+ if (DeclType->isUnionType())
+ break;
+ }
+ // FIXME: Implement flexible array initialization GCC extension (it's a
+ // really messy extension to implement, unfortunately...the necessary
+ // information isn't actually even here!)
+ }
+ } else if (DeclType->isArrayType()) {
+ // Check for the special-case of initializing an array with a string.
+ if (startIndex < IList->getNumInits()) {
+ if (StringLiteral *lit = IsStringLiteralInit(IList->getInit(startIndex),
+ DeclType)) {
+ CheckStringLiteralInit(lit, DeclType);
+ ++startIndex;
+ if (topLevel && startIndex < IList->getNumInits()) {
+ // We have leftover initializers; warn
+ Diag(IList->getInit(startIndex)->getLocStart(),
+ diag::err_excess_initializers_in_char_array_initializer,
+ IList->getInit(startIndex)->getSourceRange());
+ }
+ return false;
+ }
+ }
+ int maxElements;
+ if (DeclType->isIncompleteArrayType()) {
+ // FIXME: use a proper constant
+ maxElements = 0x7FFFFFFF;
+ } else if (const VariableArrayType *VAT =
+ DeclType->getAsVariableArrayType()) {
+ // Check for VLAs; in standard C it would be possible to check this
+ // earlier, but I don't know where clang accepts VLAs (gcc accepts
+ // them in all sorts of strange places).
+ Diag(VAT->getSizeExpr()->getLocStart(),
+ diag::err_variable_object_no_init,
+ VAT->getSizeExpr()->getSourceRange());
+ hadError = true;
+ maxElements = 0x7FFFFFFF;
+ } else {
+ const ConstantArrayType *CAT = DeclType->getAsConstantArrayType();
+ maxElements = static_cast<int>(CAT->getSize().getZExtValue());
+ }
+ QualType elementType = DeclType->getAsArrayType()->getElementType();
+ int numElements = 0;
+ for (int i = 0; i < maxElements; ++i, ++numElements) {
+ // Don't attempt to go past the end of the init list
+ if (startIndex >= IList->getNumInits())
+ break;
+ Expr* expr = IList->getInit(startIndex);
+ if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+ unsigned newIndex = 0;
+ hadError |= CheckInitializerListTypes(SubInitList, elementType,
+ true, newIndex);
+ ++startIndex;
+ } else {
+ hadError |= CheckInitializerListTypes(IList, elementType,
+ false, startIndex);
+ }
+ }
+ if (DeclType->isIncompleteArrayType()) {
+ // If this is an incomplete array type, the actual type needs to
+ // be calculated here
+ if (numElements == 0) {
+ // Sizing an array implicitly to zero is not allowed
+ // (It could in theory be allowed, but it doesn't really matter.)
+ Diag(IList->getLocStart(),
+ diag::err_at_least_one_initializer_needed_to_size_array);
+ hadError = true;
+ } else {
+ llvm::APSInt ConstVal(32);
+ ConstVal = numElements;
+ DeclType = Context.getConstantArrayType(elementType, ConstVal,
+ ArrayType::Normal, 0);
+ }
+ }
+ } else {
+ assert(0 && "Aggregate that isn't a function or array?!");
+ }
+ } else {
+ // In C, all types are either scalars or aggregates, but
+ // additional handling is needed here for C++ (and possibly others?).
+ assert(0 && "Unsupported initializer type");
+ }
+
+ // If this init list is a base list, we set the type; an initializer doesn't
+ // fundamentally have a type, but this makes the ASTs a bit easier to read
+ if (topLevel)
+ IList->setType(DeclType);
+
+ if (topLevel && startIndex < IList->getNumInits()) {
+ // We have leftover initializers; warn
+ Diag(IList->getInit(startIndex)->getLocStart(),
+ diag::warn_excess_initializers,
+ IList->getInit(startIndex)->getSourceRange());
+ }
+ return hadError;
+}
+
+bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {
+ // 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.
+ if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType())
+ return Diag(VAT->getSizeExpr()->getLocStart(),
+ diag::err_variable_object_no_init,
+ VAT->getSizeExpr()->getSourceRange());
+
+ InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
+ if (!InitList) {
+ // FIXME: Handle wide strings
+ if (StringLiteral *strLiteral = IsStringLiteralInit(Init, DeclType))
+ return CheckStringLiteralInit(strLiteral, DeclType);
+
+ if (DeclType->isArrayType())
+ return Diag(Init->getLocStart(),
+ diag::err_array_init_list_required,
+ Init->getSourceRange());
+
+ return CheckSingleInitializer(Init, DeclType);
+ }
+ unsigned newIndex = 0;
+ return CheckInitializerListTypes(InitList, DeclType, true, newIndex);
+}
+
+Sema::DeclTy *
+Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
+ ScopedDecl *LastDeclarator = dyn_cast_or_null<ScopedDecl>((Decl *)lastDecl);
+ IdentifierInfo *II = D.getIdentifier();
+
+ // All of these full declarators require an identifier. If it doesn't have
+ // one, the ParsedFreeStandingDeclSpec action should be used.
+ if (II == 0) {
+ Diag(D.getDeclSpec().getSourceRange().getBegin(),
+ diag::err_declarator_need_ident,
+ D.getDeclSpec().getSourceRange(), D.getSourceRange());
+ return 0;
+ }
+
+ // 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();
+
+ // See if this is a redefinition of a variable in the same scope.
+ ScopedDecl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
+ D.getIdentifierLoc(), S);
+ ScopedDecl *New;
+ bool InvalidDecl = false;
+
+ QualType R = GetTypeForDeclarator(D, S);
+ assert(!R.isNull() && "GetTypeForDeclarator() returned null type");
+
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, LastDeclarator);
+ if (!NewTD) return 0;
+
+ // Handle attributes prior to checking for duplicates in MergeVarDecl
+ HandleDeclAttributes(NewTD, D.getDeclSpec().getAttributes(),
+ D.getAttributes());
+ // Merge the decl with the existing one if appropriate. If the decl is
+ // in an outer scope, it isn't the same thing.
+ if (PrevDecl && S->isDeclScope(PrevDecl)) {
+ NewTD = MergeTypeDefDecl(NewTD, PrevDecl);
+ if (NewTD == 0) return 0;
+ }
+ New = NewTD;
+ if (S->getParent() == 0) {
+ // C99 6.7.7p2: If a typedef name specifies a variably modified type
+ // then it shall have block scope.
+ if (NewTD->getUnderlyingType()->isVariablyModifiedType()) {
+ // FIXME: Diagnostic needs to be fixed.
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_illegal_vla);
+ InvalidDecl = true;
+ }
+ }
+ } else if (R.getTypePtr()->isFunctionType()) {
+ FunctionDecl::StorageClass SC = FunctionDecl::None;
+ switch (D.getDeclSpec().getStorageClassSpec()) {
+ default: assert(0 && "Unknown storage class!");
+ case DeclSpec::SCS_auto:
+ case DeclSpec::SCS_register:
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_func,
+ R.getAsString());
+ InvalidDecl = true;
+ break;
+ case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break;
+ case DeclSpec::SCS_extern: SC = FunctionDecl::Extern; break;
+ case DeclSpec::SCS_static: SC = FunctionDecl::Static; break;
+ case DeclSpec::SCS_private_extern: SC = FunctionDecl::PrivateExtern;break;
+ }
+
+ bool isInline = D.getDeclSpec().isInlineSpecified();
+ FunctionDecl *NewFD = FunctionDecl::Create(Context, D.getIdentifierLoc(),
+ II, R, SC, isInline,
+ LastDeclarator);
+ // Handle attributes.
+ HandleDeclAttributes(NewFD, D.getDeclSpec().getAttributes(),
+ D.getAttributes());
+
+ // 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.
+ if (PrevDecl) {
+ NewFD = MergeFunctionDecl(NewFD, PrevDecl);
+ if (NewFD == 0) return 0;
+ }
+ New = NewFD;
+ } else {
+ if (R.getTypePtr()->isObjCInterfaceType()) {
+ Diag(D.getIdentifierLoc(), diag::err_statically_allocated_object,
+ D.getIdentifier()->getName());
+ InvalidDecl = true;
+ }
+
+ VarDecl *NewVD;
+ VarDecl::StorageClass SC;
+ switch (D.getDeclSpec().getStorageClassSpec()) {
+ 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;
+ }
+ if (S->getParent() == 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) {
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope,
+ R.getAsString());
+ InvalidDecl = true;
+ }
+ NewVD = FileVarDecl::Create(Context, D.getIdentifierLoc(), II, R, SC,
+ LastDeclarator);
+ } else {
+ NewVD = BlockVarDecl::Create(Context, D.getIdentifierLoc(), II, R, SC,
+ LastDeclarator);
+ }
+ // Handle attributes prior to checking for duplicates in MergeVarDecl
+ HandleDeclAttributes(NewVD, D.getDeclSpec().getAttributes(),
+ D.getAttributes());
+
+ // 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
+ if (NewVD->hasLocalStorage()) {
+ QualType AutoTy = NewVD->getCanonicalType();
+ if (const ArrayType *AT = AutoTy->getAsArrayType())
+ AutoTy = AT->getElementType().getCanonicalType();
+ if (AutoTy.getAddressSpace() != 0) {
+ Diag(D.getIdentifierLoc(), diag::err_as_qualified_auto_decl);
+ InvalidDecl = true;
+ }
+ }
+ // Merge the decl with the existing one if appropriate. If the decl is
+ // in an outer scope, it isn't the same thing.
+ if (PrevDecl && S->isDeclScope(PrevDecl)) {
+ NewVD = MergeVarDecl(NewVD, PrevDecl);
+ if (NewVD == 0) return 0;
+ }
+ New = NewVD;
+ }
+
+ // If this has an identifier, add it to the scope stack.
+ if (II) {
+ New->setNext(II->getFETokenInfo<ScopedDecl>());
+ II->setFETokenInfo(New);
+ S->AddDecl(New);
+ }
+ // If any semantic error occurred, mark the decl as invalid.
+ if (D.getInvalidType() || InvalidDecl)
+ New->setInvalidDecl();
+
+ return New;
+}
+
+bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
+ SourceLocation loc;
+ // FIXME: Remove the isReference check and handle assignment to a reference.
+ if (!DclT->isReferenceType() && !Init->isConstantExpr(Context, &loc)) {
+ assert(loc.isValid() && "isConstantExpr didn't return a loc!");
+ Diag(loc, diag::err_init_element_not_constant, Init->getSourceRange());
+ return true;
+ }
+ return false;
+}
+
+void Sema::AddInitializerToDecl(DeclTy *dcl, ExprTy *init) {
+ Decl *RealDecl = static_cast<Decl *>(dcl);
+ Expr *Init = static_cast<Expr *>(init);
+ assert(Init && "missing initializer");
+
+ // If there is no declaration, there was an error parsing it. Just ignore
+ // the initializer.
+ if (RealDecl == 0) {
+ delete Init;
+ return;
+ }
+
+ VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
+ if (!VDecl) {
+ Diag(dyn_cast<ScopedDecl>(RealDecl)->getLocation(),
+ diag::err_illegal_initializer);
+ RealDecl->setInvalidDecl();
+ return;
+ }
+ // Get the decls type and save a reference for later, since
+ // CheckInitializerTypes may change it.
+ QualType DclT = VDecl->getType(), SavT = DclT;
+ if (BlockVarDec