diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2297 |
1 files changed, 2297 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp new file mode 100644 index 00000000000..7914e865741 --- /dev/null +++ b/clang/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 (BlockVarDecl *BVD = dyn_cast<BlockVarDecl>(VDecl)) { + VarDecl::StorageClass SC = BVD->getStorageClass(); + if (SC == VarDecl::Extern) { // C99 6.7.8p5 + Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); + BVD->setInvalidDecl(); + } else if (!BVD->isInvalidDecl()) { + if (CheckInitializerTypes(Init, DclT)) + BVD->setInvalidDecl(); + if (SC == VarDecl::Static) // C99 6.7.8p4. + CheckForConstantInitializer(Init, DclT); + } + } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(VDecl)) { + if (FVD->getStorageClass() == VarDecl::Extern) + Diag(VDecl->getLocation(), diag::warn_extern_init); + if (!FVD->isInvalidDecl()) + if (CheckInitializerTypes(Init, DclT)) + FVD->setInvalidDecl(); + + // C99 6.7.8p4. All file scoped initializers need to be constant. + CheckForConstantInitializer(Init, DclT); + } + // 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. + if (!VDecl->isInvalidDecl() && (DclT != SavT)) { + VDecl->setType(DclT); + Init->setType(DclT); + } + + // Attach the initializer to the decl. + VDecl->setInit(Init); + return; +} + +/// 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. + Decl *GroupDecl = static_cast<Decl*>(group); + if (GroupDecl == 0) + return 0; + + ScopedDecl *Group = dyn_cast<ScopedDecl>(GroupDecl); + ScopedDecl *NewGroup = 0; + if (Group->getNextDeclarator() == 0) + NewGroup = Group; + else { // reverse the list. + while (Group) { + ScopedDecl *Next = Group->getNextDeclarator(); + Group->setNextDeclarator(NewGroup); + NewGroup = Group; + Group = Next; + } + } + // Perform semantic analysis that depends on having fully processed both + // the declarator and initializer. + for (ScopedDecl *ID = NewGroup; ID; ID = ID->getNextDeclarator()) { + VarDecl *IDecl = dyn_cast<VarDecl>(ID); + if (!IDecl) + continue; + FileVarDecl *FVD = dyn_cast<FileVarDecl>(IDecl); + BlockVarDecl *BVD = dyn_cast<BlockVarDecl>(IDecl); + QualType T = IDecl->getType(); + + // 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 ((FVD || BVD) && IDecl->getStorageClass() == VarDecl::Static) { + if (T->getAsVariableArrayType()) { + Diag(IDecl->getLocation(), diag::err_typecheck_illegal_vla); + IDecl->setInvalidDecl(); + } + } + // 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... + if (BVD && IDecl->getStorageClass() != VarDecl::Extern) { + if (T->isIncompleteType()) { + Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type, + T.getAsString()); + 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). + if (FVD && !FVD->getInit() && (FVD->getStorageClass() == VarDecl::Static || + FVD->getStorageClass() == VarDecl::None)) { + if (T->isIncompleteArrayType()) { + // C99 6.9.2 (p2, p5): Implicit initialization causes an incomplete + // array to be completed. Don't issue a diagnostic. + } else if (T->isIncompleteType()) { + // 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. + Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type, + T.getAsString()); + IDecl->setInvalidDecl(); + } + } + } + return NewGroup; +} + +// Called from Sema::ParseStartOfFunctionDef(). +ParmVarDecl * +Sema::ActOnParamDeclarator(struct DeclaratorChunk::ParamInfo &PI, + Scope *FnScope) { + IdentifierInfo *II = PI.Ident; + // 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. + if (/*Decl *PrevDecl = */LookupScopedDecl(II, Decl::IDNS_Ordinary, + PI.IdentLoc, FnScope)) { + + } + + // FIXME: Handle storage class (auto, register). No declarator? + // TODO: Chain to previous parameter with the prevdeclarator chain? + + // 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)... + // + QualType parmDeclType = QualType::getFromOpaquePtr(PI.TypeInfo); + if (const ArrayType *AT = parmDeclType->getAsArrayType()) { + // int x[restrict 4] -> int *restrict + parmDeclType = Context.getPointerType(AT->getElementType()); + parmDeclType = parmDeclType.getQualifiedType(AT->getIndexTypeQualifier()); + } else if (parmDeclType->isFunctionType()) + parmDeclType = Context.getPointerType(parmDeclType); + + ParmVarDecl *New = ParmVarDecl::Create(Context, PI.IdentLoc, II, parmDeclType, + VarDecl::None, 0); + + if (PI.InvalidType) + New->setInvalidDecl(); + + // If this has an identifier, add it to the scope stack. + if (II) { + New->setNext(II->getFETokenInfo<ScopedDecl>()); + II->setFETokenInfo(New); + FnScope->AddDecl(New); + } + + HandleDeclAttributes(New, PI.AttrList, 0); + return New; +} + +Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { + assert(CurFunctionDecl == 0 && "Function parsing confused"); + assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && + "Not a function declarator!"); + DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + + // 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) { + if (FTI.ArgInfo[i].TypeInfo == 0) { + Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared, + FTI.ArgInfo[i].Ident->getName()); + // Implicitly declare the argument as type 'int' for lack of a better + // type. + FTI.ArgInfo[i].TypeInfo = Context.IntTy.getAsOpaquePtr(); + } + } + + // Since this is a function definition, act as though we have information + // about the arguments. + if (FTI.NumArgs) + FTI.hasPrototype = true; + } else { + // FIXME: Diagnose arguments without names in C. + + } + + Scope *GlobalScope = FnBodyScope->getParent(); + + // See if this is a redefinition. + ScopedDecl *PrevDcl = LookupScopedDecl(D.getIdentifier(), Decl::IDNS_Ordinary, + D.getIdentifierLoc(), GlobalScope); + if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(PrevDcl)) { + if (FD->getBody()) { + Diag(D.getIdentifierLoc(), diag::err_redefinition, + D.getIdentifier()->getName()); + Diag(FD->getLocation(), diag::err_previous_definition); + } + } + Decl *decl = static_cast<Decl*>(ActOnDeclarator(GlobalScope, D, 0)); + FunctionDecl *FD = cast<FunctionDecl>(decl); + CurFunctionDecl = FD; + + // 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 single void argument. + if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && + !QualType::getFromOpaquePtr(FTI.ArgInfo[0].TypeInfo).getCVRQualifiers() && + QualType::getFromOpaquePtr(FTI.ArgInfo[0].TypeInfo)->isVoidType()) { + // empty arg list, don't push any params. + } else { + for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { + Params.push_back(ActOnParamDeclarator(D.getTypeObject(0).Fun.ArgInfo[i], + FnBodyScope)); + } + } + + FD->setParams(&Params[0], Params.size()); + + return FD; +} + +Sema::DeclTy *Sema::ActOnFinishFunctionBody(DeclTy *D, StmtTy *Body) { + Decl *dcl = static_cast<Decl *>(D); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(dcl)) { + FD->setBody((Stmt*)Body); + assert(FD == CurFunctionDecl && "Function parsing confused"); + CurFunctionDecl = 0; + } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(dcl)) { + MD->setBody((Stmt*)Body); + CurMethodDecl = 0; + } + // 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. + Diag(L->getIdentLoc(), diag::err_undeclared_label_use, L->getName()); + + // 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. + if (Body) { + L->setSubStmt(new NullStmt(L->getIdentLoc())); + cast<CompoundStmt>((Stmt*)Body)->push_back(L); + } else { + // The whole function wasn't parsed correctly, just delete this. + delete L; + } + } + } + LabelMap.clear(); + + return D; +} + +/// ImplicitlyDefineFunction - An undeclared identifier was used in a function +/// call, forming a call to an implicitly defined function (per C99 6.5.1p2). +ScopedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, + IdentifierInfo &II, Scope *S) { + if (getLangOptions().C99) // Extension in C99. + Diag(Loc, diag::ext_implicit_function_decl, II.getName()); + else // Legal in C90, but warn about it. + Diag(Loc, diag::warn_implicit_function_decl, II.getName()); + + // 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(); + const char *Dummy; + DeclSpec DS; + bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy); + Error = Error; // Silence warning. + assert(!Error && "Error setting up implicit decl!"); + Declarator D(DS, Declarator::BlockContext); + D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, Loc)); + D.SetIdentifier(&II, Loc); + + // 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(); + + return dyn_cast<ScopedDecl>(static_cast<Decl*>(ActOnDeclarator(S, D, 0))); +} + + +TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, + ScopedDecl *LastDeclarator) { + assert(D.getIdentifier() && "Wrong callback for declspec without declarator"); + assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); + + // Scope manipulation handled by caller. + TypedefDecl *NewTD = TypedefDecl::Create(Context, D.getIdentifierLoc(), + D.getIdentifier(), + T, LastDeclarator); + if (D.getInvalidType()) + NewTD->setInvalidDecl(); + return NewTD; +} + +/// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'. In the +/// 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. +Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, + SourceLocation KWLoc, IdentifierInfo *Name, + SourceLocation NameLoc, AttributeList *Attr) { + // If this is a use of an existing tag, it must have a name. + assert((Name != 0 || TK == TK_Definition) && + "Nameless record must be a definition!"); + + Decl::Kind Kind; + switch (TagType) { + default: assert(0 && "Unknown tag type!"); + case DeclSpec::TST_struct: Kind = Decl::Struct; break; + case DeclSpec::TST_union: Kind = Decl::Union; break; +//case DeclSpec::TST_class: Kind = Decl::Class; break; + case DeclSpec::TST_enum: Kind = Decl::Enum; break; + } + + // If this is a named struct, check to see if there was a previous forward + // declaration or definition. + if (TagDecl *PrevDecl = + dyn_cast_or_null<TagDecl>(LookupScopedDecl(Name, Decl::IDNS_Tag, + NameLoc, S))) { + + // 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 + // rementions the tag), reuse the decl. + if (TK == TK_Reference || S->isDeclScope(PrevDecl)) { + // Make sure that this wasn't declared as an enum and now used as a struct + // or something similar. + if (PrevDecl->getKind() != Kind) { + Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName()); + Diag(PrevDecl->getLocation(), diag::err_previous_use); + } + + // If this is a use or a forward declaration, we're good. + if (TK != TK_Definition) + return PrevDecl; + + // Diagnose attempts to redefine a tag. + if (PrevDecl->isDefinition()) { + Diag(NameLoc, diag::err_redefinition, Name->getName()); + Diag(PrevDecl->getLocation(), diag::err_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; + } else { + // Okay, this is definition of a previously declared or referenced tag. + // Move the location of the decl to be the definition site. + PrevDecl->setLocation(NameLoc); + return PrevDecl; + } + } + // If we get here, this is a definition of a new struct type in a nested + // scope, e.g. "struct foo; void bar() { struct foo; }", just create a new + // type. + } + + // 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; + + // Otherwise, if this is the first time we've seen this tag, create the decl. + TagDecl *New; + switch (Kind) { + default: assert(0 && "Unknown tag kind!"); + case Decl::Enum: + // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: + // enum X { A, B, C } D; D should chain to X. + New = EnumDecl::Create(Context, Loc, Name, 0); + // If this is an undefined enum, warn. + if (TK != TK_Definition) Diag(Loc, diag::ext_forward_ref_enum); + break; + case Decl::Union: + case Decl::Struct: + case Decl::Class: + // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: + // struct X { int A; } D; D should chain to X. + New = RecordDecl::Create(Context, Kind, Loc, Name, 0); + break; + } + + // If this has an identifier, add it to the scope stack. + if (Name) { + // 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. + New->setNext(Name->getFETokenInfo<ScopedDecl>()); + Name->setFETokenInfo(New); + S->AddDecl(New); + } + + HandleDeclAttributes(New, Attr, 0); + return New; +} + +/// ActOnField - Each field of a struct/union/class is passed into this in order +/// to create a FieldDecl object for it. +Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagDecl, + SourceLocation DeclStart, + Declarator &D, ExprTy *BitfieldWidth) { + 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! + + + if (BitWidth) { + // TODO: Validate. + //printf("WARNING: BITFIELDS IGNORED!\n"); + + // 6.7.2.1p3 + // 6.7.2.1p4 + + } else { + // Not a bitfield. + + // validate II. + + } + + QualType T = GetTypeForDeclarator(D, S); + assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); + bool InvalidDecl = false; + + // 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()) { + // FIXME: This diagnostic needs work + Diag(Loc, diag::err_typecheck_illegal_vla, Loc); + InvalidDecl = true; + } + // FIXME: Chain fielddecls together. + FieldDecl *NewFD; + + if (isa<RecordDecl>(static_cast<Decl *>(TagDecl))) + NewFD = new FieldDecl(Loc, II, T, BitWidth); + else if (isa<ObjCInterfaceDecl>(static_cast<Decl *>(TagDecl)) || + isa<ObjCImplementationDecl>(static_cast<Decl *>(TagDecl)) || + isa<ObjCCategoryDecl>(static_cast<Decl *>(TagDecl)) || + // FIXME: ivars are currently used to model properties, and + // properties can appear within a protocol. + // See corresponding FIXME in DeclObjC.h:ObjCPropertyDecl. + isa<ObjCProtocolDecl>(static_cast<Decl *>(TagDecl))) + NewFD = new ObjCIvarDecl(Loc, II, T); + else + assert(0 && "Sema::ActOnField(): Unknown TagDecl"); + + HandleDeclAttributes(NewFD, D.getDeclSpec().getAttributes(), + D.getAttributes()); + + if (D.getInvalidType() || InvalidDecl) + NewFD->setInvalidDecl(); + return NewFD; +} + +/// TranslateIvarVisibility - Translate visibility from a token ID to an +/// AST enum value. +static ObjCIvarDecl::AccessControl +TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { + switch (ivarVisibility) { + 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; + default: assert(false && "Unknown visitibility kind"); + } +} + +void Sema::ActOnFields(Scope* S, + SourceLocation RecLoc, DeclTy *RecDecl, + DeclTy **Fields, unsigned NumFields, + SourceLocation LBrac, SourceLocation RBrac, + tok::ObjCKeywordKind *visibility) { + Decl *EnclosingDecl = static_cast<Decl*>(RecDecl); + assert(EnclosingDecl && "missing record or interface decl"); + RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl); + + if (Record && Record->isDefinition()) { + // Diagnose code like: + // struct S { struct S {} X; }; + // We discover this when we complete the outer S. Reject and ignore the + // outer S. + Diag(Record->getLocation(), diag::err_nested_redefinition, + Record->getKindName()); + Diag(RecLoc, diag::err_previous_definition); + Record->setInvalidDecl(); + return; + } + // Verify that all the fields are okay. + unsigned NumNamedMembers = 0; + llvm::SmallVector<FieldDecl*, 32> RecFields; + llvm::SmallSet<const IdentifierInfo*, 32> FieldIDs; + + for (unsigned i = 0; i != NumFields; ++i) { + + FieldDecl *FD = cast_or_null<FieldDecl>(static_cast<Decl*>(Fields[i])); + assert(FD && "missing field decl"); + + // Remember all fields. + RecFields.push_back(FD); + + // Get the type for the field. + Type *FDTy = FD->getType().getTypePtr(); + + // If we have visibility info, make sure the AST is set accordingly. + if (visibility) + cast<ObjCIvarDecl>(FD)->setAccessControl( + TranslateIvarVisibility(visibility[i])); + + // C99 6.7.2.1p2 - A field may not be a function type. + if (FDTy->isFunctionType()) { + Diag(FD->getLocation(), diag::err_field_declared_as_function, + FD->getName()); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + // C99 6.7.2.1p2 - A field may not be an incomplete type except... + if (FDTy->isIncompleteType()) { + if (!Record) { // Incomplete ivar type is always an error. + Diag(FD->getLocation(), diag::err_field_incomplete, FD->getName()); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + if (i != NumFields-1 || // ... that the last member ... + Record->getKind() != Decl::Struct || // ... of a structure ... + !FDTy->isArrayType()) { //... may have incomplete array type. + Diag(FD->getLocation(), diag::err_field_incomplete, FD->getName()); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + if (NumNamedMembers < 1) { //... must have more than named member ... + Diag(FD->getLocation(), diag::err_flexible_array_empty_struct, + FD->getName()); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + // Okay, we have a legal flexible array member at the end of the struct. + if (Record) + Record->setHasFlexibleArrayMember(true); + } + /// 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. + if (const RecordType *FDTTy = FDTy->getAsRecordType()) { + if (FDTTy->getDecl()->hasFlexibleArrayMember()) { + // If this is a member of a union, then entire union becomes "flexible". + if (Record && Record->getKind() == Decl::Union) { + Record->setHasFlexibleArrayMember(true); + } 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) { + Diag(FD->getLocation(), diag::err_variable_sized_type_in_struct, + FD->getName()); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + // We support flexible arrays at the end of structs in other structs + // as an extension. + Diag(FD->getLocation(), diag::ext_flexible_array_in_struct, + FD->getName()); + if (Record) + Record->setHasFlexibleArrayMember(true); + } + } + } + /// A field cannot be an Objective-c object + if (FDTy->isObjCInterfaceType()) { + Diag(FD->getLocation(), diag::err_statically_allocated_object, + FD->getName()); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + // Keep track of the number of named members. + if (IdentifierInfo *II = FD->getIdentifier()) { + // Detect duplicate member names. + if (!FieldIDs.insert(II)) { + Diag(FD->getLocation(), diag::err_duplicate_member, II->getName()); + // Find the previous decl. + SourceLocation PrevLoc; + for (unsigned i = 0, e = RecFields.size(); ; ++i) { + assert(i != e && "Didn't find previous def!"); + if (RecFields[i]->getIdentifier() == II) { + PrevLoc = RecFields[i]->getLocation(); + break; + } + } + Diag(PrevLoc, diag::err_previous_definition); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + ++NumNamedMembers; + } + } + + // Okay, we successfully defined 'Record'. + if (Record) { + Record->defineBody(&RecFields[0], RecFields.size()); + Consumer.HandleTagDeclDefinition(Record); + } else { + ObjCIvarDecl **ClsFields = reinterpret_cast<ObjCIvarDecl**>(&RecFields[0]); + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl)) + ID->addInstanceVariablesToClass(ClsFields, RecFields.size(), RBrac); + else if (ObjCImplementationDecl *IMPDecl = + dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { + assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl"); + IMPDecl->ObjCAddInstanceVariablesToClassImpl(ClsFields, RecFields.size()); + CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac); + } + } +} + +Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl, + DeclTy *lastEnumConst, + SourceLocation IdLoc, IdentifierInfo *Id, + SourceLocation EqualLoc, ExprTy *val) { + theEnumDecl = theEnumDecl; // silence unused warning. + EnumConstantDecl *LastEnumConst = + cast_or_null<EnumConstantDecl>(static_cast<Decl*>(lastEnumConst)); + Expr *Val = static_cast<Expr*>(val); + + // 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(); + + // Verify that there isn't already something declared with this name in this + // scope. + if (ScopedDecl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary, + IdLoc, S)) { + if (S->isDeclScope(PrevDecl)) { + if (isa<EnumConstantDecl>(PrevDecl)) + Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName()); + else + Diag(IdLoc, diag::err_redefinition, Id->getName()); + Diag(PrevDecl->getLocation(), diag::err_previous_definition); + delete Val; + return 0; + } + } + + llvm::APSInt EnumVal(32); + QualType EltTy; + if (Val) { + // Make sure to promote the operand type to int. + UsualUnaryConversions(Val); + + // C99 6.7.2.2p2: Make sure we have an integer constant expression. + SourceLocation ExpLoc; + if (!Val->isIntegerConstantExpr(EnumVal, Context, &ExpLoc)) { + Diag(ExpLoc, diag::err_enum_value_not_integer_constant_expr, + Id->getName()); + delete Val; + Val = 0; // Just forget about it. + } else { + EltTy = Val->getType(); + } + } + + if (!Val) { + if (LastEnumConst) { + // Assign the last value + 1. + EnumVal = LastEnumConst->getInitVal(); + ++EnumVal; + + // Check for overflow on increment. + if (EnumVal < LastEnumConst->getInitVal()) + Diag(IdLoc, diag::warn_enum_value_overflow); + + EltTy = LastEnumConst->getType(); + } else { + // First value, set to zero. + EltTy = Context.IntTy; + EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy))); + } + } + + EnumConstantDecl *New = + EnumConstantDecl::Create(Context, IdLoc, Id, EltTy, Val, EnumVal, + LastEnumConst); + + // Register this decl in the current scope stack. + New->setNext(Id->getFETokenInfo<ScopedDecl>()); + Id->setFETokenInfo(New); + S->AddDecl(New); + return New; +} + +void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, + DeclTy **Elements, unsigned NumElements) { + EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX)); + assert(!Enum->isDefinition() && "Enum redefinitions can't reach here"); + + // 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. + unsigned IntWidth = Context.Target.getIntWidth(); + + // 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; + + EnumConstantDecl *EltList = 0; + 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. + + // If the enum value doesn't fit in an int, emit an extension warning. + const llvm::APSInt &InitVal = ECD->getInitVal(); + assert(InitVal.getBitWidth() >= IntWidth && + "Should have promoted value to int"); + if (InitVal.getBitWidth() > IntWidth) { + llvm::APSInt V(InitVal); + V.trunc(IntWidth); + V.extend(InitVal.getBitWidth()); + if (V != InitVal) + Diag(ECD->getLocation(), diag::ext_enum_value_not_int, + InitVal.toString()); + } + + // Keep track of the size of positive and negative values. + if (InitVal.isUnsigned() || InitVal.isNonNegative()) + NumPositiveBits = std::max(NumPositiveBits, + (unsigned)InitVal.getActiveBits()); + else + NumNegativeBits = std::max(NumNegativeBits, + (unsigned)InitVal.getMinSignedBits()); + + // Keep track of whether every enum element has type int (very commmon). + if (AllElementsInt) + AllElementsInt = ECD->getType() == Context.IntTy; + + ECD->setNextDeclarator(EltList); + EltList = ECD; + } + + // Figure out the type that should be used for this enum. + // FIXME: Support attribute(packed) on enums and -fshort-enums. + QualType BestType; + unsigned BestWidth; + + if (NumNegativeBits) { + // If there is a negative value, figure out the smallest integer type (of + // int/long/longlong) that fits. + if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) { + BestType = Context.IntTy; + BestWidth = IntWidth; + } else { + BestWidth = Context.Target.getLongWidth(); + + if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) + BestType = Context.LongTy; + else { + BestWidth = Context.Target.getLongLongWidth(); + + if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth) + 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. + if (NumPositiveBits <= IntWidth) { + BestType = Context.UnsignedIntTy; + BestWidth = IntWidth; + } else if (NumPositiveBits <= + (BestWidth = Context.Target.getLongWidth())) { + BestType = Context.UnsignedLongTy; + } else { + BestWidth = Context.Target.getLongLongWidth(); + assert(NumPositiveBits <= BestWidth && + "How could an initializer get larger than ULL?"); + BestType = Context.UnsignedLongLongTy; + } + } + + // 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'. + if (ECD->getType() == Context.IntTy) { + // Make sure the init value is signed. + llvm::APSInt IV = ECD->getInitVal(); + IV.setIsSigned(true); + ECD->setInitVal(IV); + continue; // Already int type. + } + + // 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! + 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. + ECD->setInitExpr(new ImplicitCastExpr(NewTy, ECD->getInitExpr())); + ECD->setType(NewTy); + } + + Enum->defineElements(EltList, BestType); + Consumer.HandleTagDeclDefinition(Enum); +} + +Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, + ExprTy *expr) { + StringLiteral *AsmString = cast<StringLiteral>((Expr*)expr); + + return new FileScopeAsmDecl(Loc, AsmString); +} + +Sema::DeclTy* Sema::ActOnLinkageSpec(SourceLocation Loc, + SourceLocation LBrace, + SourceLocation RBrace, + const char *Lang, + unsigned StrSize, + DeclTy *D) { + LinkageSpecDecl::LanguageIDs Language; + Decl *dcl = static_cast<Decl *>(D); + if (strncmp(Lang, "\"C\"", StrSize) == 0) + Language = LinkageSpecDecl::lang_c; + else if (strncmp(Lang, "\"C++\"", StrSize) == 0) + Language = LinkageSpecDecl::lang_cxx; + else { + Diag(Loc, diag::err_bad_language); + return 0; + } + + // FIXME: Add all the various semantics of linkage specifications + return new LinkageSpecDecl(Loc, Language, dcl); +} + +void Sema::HandleDeclAttribute(Decl *New, AttributeList *Attr) { + + switch (Attr->getKind()) { + case AttributeList::AT_vector_size: + if (ValueDecl *vDecl = dyn_cast<ValueDecl>(New)) { + QualType newType = HandleVectorTypeAttribute(vDecl->getType(), Attr); + if (!newType.isNull()) // install the new vector type into the decl + vDecl->setType(newType); + } + if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) { + QualType newType = HandleVectorTypeAttribute(tDecl->getUnderlyingType(), + Attr); + if (!newType.isNull()) // install the new vector type into the decl + tDecl->setUnderlyingType(newType); + } + break; + case AttributeList::AT_ocu_vector_type: + if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) + HandleOCUVectorTypeAttribute(tDecl, Attr); + else + Diag(Attr->getLoc(), + diag::err_typecheck_ocu_vector_not_typedef); + break; + case AttributeList::AT_address_space: + if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) { + QualType newType = HandleAddressSpaceTypeAttribute( + tDecl->getUnderlyingType(), + Attr); + tDecl->setUnderlyingType(newType); + } else if (ValueDecl *vDecl = dyn_cast<ValueDecl>(New)) { + QualType newType = HandleAddressSpaceTypeAttribute(vDecl->getType(), + Attr); + // install the new addr spaced type into the decl + vDecl->setType(newType); + } + break; + case AttributeList::AT_deprecated: + HandleDeprecatedAttribute(New, Attr); + break; + case AttributeList::AT_visibility: + HandleVisibilityAttribute(New, Attr); + break; + case AttributeList::AT_weak: + HandleWeakAttribute(New, Attr); + break; + case AttributeList::AT_dllimport: + HandleDLLImportAttribute(New, Attr); + break; + case AttributeList::AT_dllexport: + HandleDLLExportAttribute(New, Attr); + break; + case AttributeList::AT_nothrow: + HandleNothrowAttribute(New, Attr); + break; + case AttributeList::AT_stdcall: + HandleStdCallAttribute(New, Attr); + break; + case AttributeList::AT_fastcall: + HandleFastCallAttribute(New, Attr); + break; + case AttributeList::AT_aligned: + HandleAlignedAttribute(New, Attr); + break; + case AttributeList::AT_packed: + HandlePackedAttribute(New, Attr); + break; + case AttributeList::AT_annotate: + HandleAnnotateAttribute(New, Attr); + break; + case AttributeList::AT_noreturn: + HandleNoReturnAttribute(New, Attr); + break; + case AttributeList::AT_format: + HandleFormatAttribute(New, Attr); + break; + default: +#if 0 + // TODO: when we have the full set of attributes, warn about unknown ones. + Diag(Attr->getLoc(), diag::warn_attribute_ignored, + Attr->getName()->getName()); +#endif + break; + } +} + +void Sema::HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix, + AttributeList *declarator_postfix) { + while (declspec_prefix) { + HandleDeclAttribute(New, declspec_prefix); + declspec_prefix = declspec_prefix->getNext(); + } + while (declarator_postfix) { + HandleDeclAttribute(New, declarator_postfix); + declarator_postfix = declarator_postfix->getNext(); + } +} + +void Sema::HandleOCUVectorTypeAttribute(TypedefDecl *tDecl, + AttributeList *rawAttr) { + QualType curType = tDecl->getUnderlyingType(); + // check the attribute arguments. + if (rawAttr->getNumArgs() != 1) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("1")); + return; + } + Expr *sizeExpr = static_cast<Expr *>(rawAttr->getArg(0)); + llvm::APSInt vecSize(32); + if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) { + Diag(rawAttr->getLoc(), diag::err_attribute_argument_not_int, + "ocu_vector_type", sizeExpr->getSourceRange()); + return; + } + // unlike gcc's vector_size attribute, we do not allow vectors to be defined + // in conjunction with complex types (pointers, arrays, functions, etc.). + Type *canonType = curType.getCanonicalType().getTypePtr(); + if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) { + Diag(rawAttr->getLoc(), diag::err_attribute_invalid_vector_type, + curType.getCanonicalType().getAsString()); + return; + } + // unlike gcc's vector_size attribute, the size is specified as the + // number of elements, not the number of bytes. + unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); + + if (vectorSize == 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_zero_size, + sizeExpr->getSourceRange()); + return; + } + // Instantiate/Install the vector type, the number of elements is > 0. + tDecl->setUnderlyingType(Context.getOCUVectorType(curType, vectorSize)); + // Remember this typedef decl, we will need it later for diagnostics. + OCUVectorDecls.push_back(tDecl); +} + +QualType Sema::HandleVectorTypeAttribute(QualType curType, + AttributeList *rawAttr) { + // check the attribute arugments. + if (rawAttr->getNumArgs() != 1) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("1")); + return QualType(); + } + Expr *sizeExpr = static_cast<Expr *>(rawAttr->getArg(0)); + llvm::APSInt vecSize(32); + if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) { + Diag(rawAttr->getLoc(), diag::err_attribute_argument_not_int, + "vector_size", sizeExpr->getSourceRange()); + return QualType(); + } + // navigate to the base type - we need to provide for vector pointers, + // vector arrays, and functions returning vectors. + Type *canonType = curType.getCanonicalType().getTypePtr(); + + if (canonType->isPointerType() || canonType->isArrayType() || + canonType->isFunctionType()) { + assert(0 && "HandleVector(): Complex type construction unimplemented"); + /* FIXME: rebuild the type from the inside out, vectorizing the inner type. + do { + if (PointerType *PT = dyn_cast<PointerType>(canonType)) + canonType = PT->getPointeeType().getTypePtr(); + else if (ArrayType *AT = dyn_cast<ArrayType>(canonType)) + canonType = AT->getElementType().getTypePtr(); + else if (FunctionType *FT = dyn_cast<FunctionType>(canonType)) + canonType = FT->getResultType().getTypePtr(); + } while (canonType->isPointerType() || canonType->isArrayType() || + canonType->isFunctionType()); + */ + } + // the base type must be integer or float. + if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) { + Diag(rawAttr->getLoc(), diag::err_attribute_invalid_vector_type, + curType.getCanonicalType().getAsString()); + return QualType(); + } + unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(curType)); + // vecSize is specified in bytes - convert to bits. + unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8); + + // the vector size needs to be an integral multiple of the type size. + if (vectorSize % typeSize) { + Diag(rawAttr->getLoc(), diag::err_attribute_invalid_size, + sizeExpr->getSourceRange()); + return QualType(); + } + if (vectorSize == 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_zero_size, + sizeExpr->getSourceRange()); + return QualType(); + } + // Instantiate the vector type, the number of elements is > 0, and not + // required to be a power of 2, unlike GCC. + return Context.getVectorType(curType, vectorSize/typeSize); +} + +void Sema::HandlePackedAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() > 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("0")); + return; + } + + if (TagDecl *TD = dyn_cast<TagDecl>(d)) + TD->addAttr(new PackedAttr); + else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) { + // If the alignment is less than or equal to 8 bits, the packed attribute + // has no effect. + if (Context.getTypeAlign(FD->getType()) <= 8) + Diag(rawAttr->getLoc(), + diag::warn_attribute_ignored_for_field_of_type, + rawAttr->getName()->getName(), FD->getType().getAsString()); + else + FD->addAttr(new PackedAttr); + } else + Diag(rawAttr->getLoc(), diag::warn_attribute_ignored, + rawAttr->getName()->getName()); +} + +void Sema::HandleNoReturnAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("0")); + return; + } + + FunctionDecl *Fn = dyn_cast<FunctionDecl>(d); + + if (!Fn) { + Diag(rawAttr->getLoc(), diag::warn_attribute_wrong_decl_type, + "noreturn", "function"); + return; + } + + d->addAttr(new NoReturnAttr()); +} + +void Sema::HandleDeprecatedAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("0")); + return; + } + + d->addAttr(new DeprecatedAttr()); +} + +void Sema::HandleVisibilityAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 1) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("1")); + return; + } + + Expr *Arg = static_cast<Expr*>(rawAttr->getArg(0)); + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + + if (Str == 0 || Str->isWide()) { + Diag(rawAttr->getLoc(), diag::err_attribute_argument_n_not_string, + "visibility", std::string("1")); + return; + } + + const char *TypeStr = Str->getStrData(); + unsigned TypeLen = Str->getByteLength(); + llvm::GlobalValue::VisibilityTypes type; + + if (TypeLen == 7 && !memcmp(TypeStr, "default", 7)) + type = llvm::GlobalValue::DefaultVisibility; + else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6)) + type = llvm::GlobalValue::HiddenVisibility; + else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8)) + type = llvm::GlobalValue::HiddenVisibility; // FIXME + else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9)) + type = llvm::GlobalValue::ProtectedVisibility; + else { + Diag(rawAttr->getLoc(), diag::warn_attribute_type_not_supported, + "visibility", TypeStr); + return; + } + + d->addAttr(new VisibilityAttr(type)); +} + +void Sema::HandleWeakAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("0")); + return; + } + + d->addAttr(new WeakAttr()); +} + +void Sema::HandleDLLImportAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("0")); + return; + } + + d->addAttr(new DLLImportAttr()); +} + +void Sema::HandleDLLExportAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("0")); + return; + } + + d->addAttr(new DLLExportAttr()); +} + +void Sema::HandleStdCallAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("0")); + return; + } + + d->addAttr(new StdCallAttr()); +} + +void Sema::HandleFastCallAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("0")); + return; + } + + d->addAttr(new FastCallAttr()); +} + +void Sema::HandleNothrowAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 0) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("0")); + return; + } + + d->addAttr(new NoThrowAttr()); +} + +/// Handle __attribute__((format(type,idx,firstarg))) attributes +/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +void Sema::HandleFormatAttribute(Decl *d, AttributeList *rawAttr) { + + if (!rawAttr->getParameterName()) { + Diag(rawAttr->getLoc(), diag::err_attribute_argument_n_not_string, + "format", std::string("1")); + return; + } + + if (rawAttr->getNumArgs() != 2) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("3")); + return; + } + + FunctionDecl *Fn = dyn_cast<FunctionDecl>(d); + if (!Fn) { + Diag(rawAttr->getLoc(), diag::warn_attribute_wrong_decl_type, + "format", "function"); + return; + } + + const FunctionTypeProto *proto = + dyn_cast<FunctionTypeProto>(Fn->getType()->getAsFunctionType()); + if (!proto) + return; + + // FIXME: in C++ the implicit 'this' function parameter also counts. + // this is needed in order to be compatible with GCC + // the index must start in 1 and the limit is numargs+1 + unsigned NumArgs = Fn->getNumParams(); + unsigned FirstIdx = 1; + + const char *Format = rawAttr->getParameterName()->getName(); + unsigned FormatLen = rawAttr->getParameterName()->getLength(); + + // Normalize the argument, __foo__ becomes foo. + if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' && + Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') { + Format += 2; + FormatLen -= 4; + } + + if (!((FormatLen == 5 && !memcmp(Format, "scanf", 5)) + || (FormatLen == 6 && !memcmp(Format, "printf", 6)) + || (FormatLen == 7 && !memcmp(Format, "strfmon", 7)) + || (FormatLen == 8 && !memcmp(Format, "strftime", 8)))) { + Diag(rawAttr->getLoc(), diag::warn_attribute_type_not_supported, + "format", rawAttr->getParameterName()->getName()); + return; + } + + // checks for the 2nd argument + Expr *IdxExpr = static_cast<Expr *>(rawAttr->getArg(0)); + llvm::APSInt Idx(Context.getTypeSize(IdxExpr->getType())); + if (!IdxExpr->isIntegerConstantExpr(Idx, Context)) { + Diag(rawAttr->getLoc(), diag::err_attribute_argument_n_not_int, + "format", std::string("2"), IdxExpr->getSourceRange()); + return; + } + + if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { + Diag(rawAttr->getLoc(), diag::err_attribute_argument_out_of_bounds, + "format", std::string("2"), IdxExpr->getSourceRange()); + return; + } + + // make sure the format string is really a string + QualType Ty = proto->getArgType(Idx.getZExtValue()-1); + if (!Ty->isPointerType() || + !Ty->getAsPointerType()->getPointeeType()->isCharType()) { + Diag(rawAttr->getLoc(), diag::err_format_attribute_not_string, + IdxExpr->getSourceRange()); + return; + } + + + // check the 3rd argument + Expr *FirstArgExpr = static_cast<Expr *>(rawAttr->getArg(1)); + llvm::APSInt FirstArg(Context.getTypeSize(FirstArgExpr->getType())); + if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, Context)) { + Diag(rawAttr->getLoc(), diag::err_attribute_argument_n_not_int, + "format", std::string("3"), FirstArgExpr->getSourceRange()); + return; + } + + // check if the function is variadic if the 3rd argument non-zero + if (FirstArg != 0) { + if (proto->isVariadic()) { + ++NumArgs; // +1 for ... + } else { + Diag(d->getLocation(), diag::err_format_attribute_requires_variadic); + return; + } + } + + // strftime requires FirstArg to be 0 because it doesn't read from any variable + // the input is just the current time + the format string + if (FormatLen == 8 && !memcmp(Format, "strftime", 8)) { + if (FirstArg != 0) { + Diag(rawAttr->getLoc(), diag::err_format_strftime_third_parameter, + FirstArgExpr->getSourceRange()); + return; + } + // if 0 it disables parameter checking (to use with e.g. va_list) + } else if (FirstArg != 0 && FirstArg != NumArgs) { + Diag(rawAttr->getLoc(), diag::err_attribute_argument_out_of_bounds, + "format", std::string("3"), FirstArgExpr->getSourceRange()); + return; + } + + d->addAttr(new FormatAttr(std::string(Format, FormatLen), + Idx.getZExtValue(), FirstArg.getZExtValue())); +} + +void Sema::HandleAnnotateAttribute(Decl *d, AttributeList *rawAttr) { + // check the attribute arguments. + if (rawAttr->getNumArgs() != 1) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("1")); + return; + } + Expr *argExpr = static_cast<Expr *>(rawAttr->getArg(0)); + StringLiteral *SE = dyn_cast<StringLiteral>(argExpr); + + // Make sure that there is a string literal as the annotation's single + // argument. + if (!SE) { + Diag(rawAttr->getLoc(), diag::err_attribute_annotate_no_string); + return; + } + d->addAttr(new AnnotateAttr(std::string(SE->getStrData(), + SE->getByteLength()))); +} + +void Sema::HandleAlignedAttribute(Decl *d, AttributeList *rawAttr) +{ + // check the attribute arguments. + if (rawAttr->getNumArgs() > 1) { + Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("1")); + return; + } + + unsigned Align = 0; + + if (rawAttr->getNumArgs() == 0) { + // FIXME: This should be the target specific maximum alignment. + // (For now we just use 128 bits which is the maximum on X86. + Align = 128; + return; + } else { + Expr *alignmentExpr = static_cast<Expr *>(rawAttr->getArg(0)); + llvm::APSInt alignment(32); + if (!alignmentExpr->isIntegerConstantExpr(alignment, Context)) { + Diag(rawAttr->getLoc(), diag::err_attribute_argument_not_int, + "aligned", alignmentExpr->getSourceRange()); + return; + } + + Align = alignment.getZExtValue() * 8; + } + + d->addAttr(new AlignedAttr(Align)); +} |