diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
commit | 9092c3e0fa01f3139b016d05d267a89e3b07747a (patch) | |
tree | 137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Sema/SemaDecl.cpp | |
parent | 4981926bf654fe5a2c3893f24ca44106b217e71e (diff) | |
download | FreeBSD-src-9092c3e0fa01f3139b016d05d267a89e3b07747a.zip FreeBSD-src-9092c3e0fa01f3139b016d05d267a89e3b07747a.tar.gz |
Update clang to r84119.
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 2571 |
1 files changed, 1818 insertions, 753 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1fd5697..606b33f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -12,28 +12,34 @@ //===----------------------------------------------------------------------===// #include "Sema.h" -#include "SemaInherit.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/Analysis/CFG.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" #include "clang/Parse/DeclSpec.h" -#include "clang/Basic/TargetInfo.h" +#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.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/SmallSet.h" +#include "clang/Lex/HeaderSearch.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include <algorithm> +#include <cstring> #include <functional> +#include <queue> using namespace clang; /// getDeclName - Return a pretty name for the specified decl if possible, or -/// an empty string if not. This is used for pretty crash reporting. +/// an empty string if not. This is used for pretty crash reporting. std::string Sema::getDeclName(DeclPtrTy d) { Decl *D = d.getAs<Decl>(); if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(D)) @@ -57,7 +63,8 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) { /// If name lookup results in an ambiguity, this routine will complain /// and then return NULL. Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, const CXXScopeSpec *SS) { + Scope *S, const CXXScopeSpec *SS, + bool isClassName) { // C++ [temp.res]p3: // A qualified-id that refers to a type and in which the // nested-name-specifier depends on a template-parameter (14.6.2) @@ -67,11 +74,20 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // // We therefore do not perform any name lookup if the result would // refer to a member of an unknown specialization. - if (SS && isUnknownSpecialization(*SS)) - return 0; + if (SS && isUnknownSpecialization(*SS)) { + if (!isClassName) + return 0; + + // We know from the grammar that this name refers to a type, so build a + // TypenameType node to describe the type. + // FIXME: Record somewhere that this TypenameType node has no "typename" + // keyword associated with it. + return CheckTypenameType((NestedNameSpecifier *)SS->getScopeRep(), + II, SS->getRange()).getAsOpaquePtr(); + } - LookupResult Result - = LookupParsedName(S, SS, &II, LookupOrdinaryName, false, false); + LookupResult Result; + LookupParsedName(Result, S, SS, &II, LookupOrdinaryName, false, false); NamedDecl *IIDecl = 0; switch (Result.getKind()) { @@ -79,15 +95,21 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, case LookupResult::FoundOverloaded: return 0; - case LookupResult::AmbiguousBaseSubobjectTypes: - case LookupResult::AmbiguousBaseSubobjects: - case LookupResult::AmbiguousReference: { + case LookupResult::Ambiguous: { + // Recover from type-hiding ambiguities by hiding the type. We'll + // do the lookup again when looking for an object, and we can + // diagnose the error then. If we don't do this, then the error + // about hiding the type will be immediately followed by an error + // that only makes sense if the identifier was treated like a type. + if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) + return 0; + // Look to see if we have a type anywhere in the list of results. for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end(); Res != ResEnd; ++Res) { if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) { - if (!IIDecl || - (*Res)->getLocation().getRawEncoding() < + if (!IIDecl || + (*Res)->getLocation().getRawEncoding() < IIDecl->getLocation().getRawEncoding()) IIDecl = *Res; } @@ -100,7 +122,6 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // perform this lookup again (e.g., as an object name), which // will produce the ambiguity, or will complain that it expected // a type name. - Result.Destroy(); return 0; } @@ -113,17 +134,17 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, } case LookupResult::Found: - IIDecl = Result.getAsDecl(); + IIDecl = Result.getFoundDecl(); break; } if (IIDecl) { QualType T; - + if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { // Check whether we can use this type (void)DiagnoseUseOfDecl(IIDecl, NameLoc); - + if (getLangOptions().CPlusPlus) { // C++ [temp.local]p2: // Within the scope of a class template specialization or @@ -143,7 +164,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { // Check whether we can use this interface. (void)DiagnoseUseOfDecl(IIDecl, NameLoc); - + T = Context.getObjCInterfaceType(IDecl); } else return 0; @@ -164,9 +185,10 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, /// where the user forgot to specify the tag. DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { // Do a tag name lookup in this scope. - LookupResult R = LookupName(S, &II, LookupTagName, false, false); + LookupResult R; + LookupName(R, S, &II, LookupTagName, false, false); if (R.getKind() == LookupResult::Found) - if (const TagDecl *TD = dyn_cast<TagDecl>(R.getAsDecl())) { + if (const TagDecl *TD = dyn_cast<TagDecl>(R.getAsSingleDecl(Context))) { switch (TD->getTagKind()) { case TagDecl::TK_struct: return DeclSpec::TST_struct; case TagDecl::TK_union: return DeclSpec::TST_union; @@ -174,24 +196,60 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { case TagDecl::TK_enum: return DeclSpec::TST_enum; } } - + return DeclSpec::TST_unspecified; } +bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + const CXXScopeSpec *SS, + TypeTy *&SuggestedType) { + // We don't have anything to suggest (yet). + SuggestedType = 0; + + // FIXME: Should we move the logic that tries to recover from a missing tag + // (struct, union, enum) from Parser::ParseImplicitInt here, instead? + + if (!SS) + Diag(IILoc, diag::err_unknown_typename) << &II; + else if (DeclContext *DC = computeDeclContext(*SS, false)) + Diag(IILoc, diag::err_typename_nested_not_found) + << &II << DC << SS->getRange(); + else if (isDependentScopeSpecifier(*SS)) { + Diag(SS->getRange().getBegin(), diag::err_typename_missing) + << (NestedNameSpecifier *)SS->getScopeRep() << II.getName() + << SourceRange(SS->getRange().getBegin(), IILoc) + << CodeModificationHint::CreateInsertion(SS->getRange().getBegin(), + "typename "); + SuggestedType = ActOnTypenameType(SourceLocation(), *SS, II, IILoc).get(); + } else { + assert(SS && SS->isInvalid() && + "Invalid scope specifier has already been diagnosed"); + } + + return true; +} - +// Determines the context to return to after temporarily entering a +// context. This depends in an unnecessarily complicated way on the +// exact ordering of callbacks from the parser. DeclContext *Sema::getContainingDC(DeclContext *DC) { - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) { - // A C++ out-of-line method will return to the file declaration context. - if (MD->isOutOfLine()) - return MD->getLexicalDeclContext(); - - // A C++ inline method is parsed *after* the topmost class it was declared - // in is fully parsed (it's "complete"). - // The parsing of a C++ inline method happens at the declaration context of - // the topmost (non-nested) class it is lexically declared in. - assert(isa<CXXRecordDecl>(MD->getParent()) && "C++ method not in Record."); - DC = MD->getParent(); + + // Functions defined inline within classes aren't parsed until we've + // finished parsing the top-level class, so the top-level class is + // the context we'll need to return to. + if (isa<FunctionDecl>(DC)) { + DC = DC->getLexicalParent(); + + // A function not defined within a class will always return to its + // lexical context. + if (!isa<CXXRecordDecl>(DC)) + return DC; + + // A C++ inline method/friend is parsed *after* the topmost class + // it was declared in is fully parsed ("complete"); the topmost + // class is the context we need to return to. while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent())) DC = RD; @@ -260,103 +318,84 @@ static bool AllowOverloadingOfFunction(Decl *PrevDecl, ASTContext &Context) { } /// Add this decl to the scope shadowed decl chains. -void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) { +void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { // Move up the scope chain until we find the nearest enclosing // non-transparent context. The declaration will be introduced into this // scope. - while (S->getEntity() && + while (S->getEntity() && ((DeclContext *)S->getEntity())->isTransparentContext()) S = S->getParent(); - S->AddDecl(DeclPtrTy::make(D)); - // Add scoped declarations into their context, so that they can be // found later. Declarations without a context won't be inserted // into any context. - CurContext->addDecl(D); - - // C++ [basic.scope]p4: - // -- exactly one declaration shall declare a class name or - // enumeration name that is not a typedef name and the other - // declarations shall all refer to the same object or - // enumerator, or all refer to functions and function templates; - // in this case the class name or enumeration name is hidden. - if (TagDecl *TD = dyn_cast<TagDecl>(D)) { - // We are pushing the name of a tag (enum or class). - if (CurContext->getLookupContext() - == TD->getDeclContext()->getLookupContext()) { - // We're pushing the tag into the current context, which might - // require some reshuffling in the identifier resolver. - IdentifierResolver::iterator - I = IdResolver.begin(TD->getDeclName()), - IEnd = IdResolver.end(); - if (I != IEnd && isDeclInScope(*I, CurContext, S)) { - NamedDecl *PrevDecl = *I; - for (; I != IEnd && isDeclInScope(*I, CurContext, S); - PrevDecl = *I, ++I) { - if (TD->declarationReplaces(*I)) { - // This is a redeclaration. Remove it from the chain and - // break out, so that we'll add in the shadowed - // declaration. - S->RemoveDecl(DeclPtrTy::make(*I)); - if (PrevDecl == *I) { - IdResolver.RemoveDecl(*I); - IdResolver.AddDecl(TD); - return; - } else { - IdResolver.RemoveDecl(*I); - break; - } - } - } + if (AddToContext) + CurContext->addDecl(D); - // There is already a declaration with the same name in the same - // scope, which is not a tag declaration. It must be found - // before we find the new declaration, so insert the new - // declaration at the end of the chain. - IdResolver.AddShadowedDecl(TD, PrevDecl); - - return; - } - } - } else if ((isa<FunctionDecl>(D) && - AllowOverloadingOfFunction(D, Context)) || - isa<FunctionTemplateDecl>(D)) { - // We are pushing the name of a function or function template, - // which might be an overloaded name. - IdentifierResolver::iterator Redecl - = std::find_if(IdResolver.begin(D->getDeclName()), - IdResolver.end(), - std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces), - D)); - if (Redecl != IdResolver.end() && - S->isDeclScope(DeclPtrTy::make(*Redecl))) { - // There is already a declaration of a function on our - // IdResolver chain. Replace it with this declaration. - S->RemoveDecl(DeclPtrTy::make(*Redecl)); - IdResolver.RemoveDecl(*Redecl); - } - } else if (isa<ObjCInterfaceDecl>(D)) { - // We're pushing an Objective-C interface into the current - // context. If there is already an alias declaration, remove it first. - for (IdentifierResolver::iterator - I = IdResolver.begin(D->getDeclName()), IEnd = IdResolver.end(); - I != IEnd; ++I) { - if (isa<ObjCCompatibleAliasDecl>(*I)) { - S->RemoveDecl(DeclPtrTy::make(*I)); - IdResolver.RemoveDecl(*I); - break; - } + // Out-of-line function and variable definitions should not be pushed into + // scope. + if ((isa<FunctionTemplateDecl>(D) && + cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->isOutOfLine()) || + (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isOutOfLine()) || + (isa<VarDecl>(D) && cast<VarDecl>(D)->isOutOfLine())) + return; + + // If this replaces anything in the current scope, + IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()), + IEnd = IdResolver.end(); + for (; I != IEnd; ++I) { + if (S->isDeclScope(DeclPtrTy::make(*I)) && D->declarationReplaces(*I)) { + S->RemoveDecl(DeclPtrTy::make(*I)); + IdResolver.RemoveDecl(*I); + + // Should only need to replace one decl. + break; } } + S->AddDecl(DeclPtrTy::make(D)); IdResolver.AddDecl(D); } +bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) { + if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) { + // Look inside the overload set to determine if any of the declarations + // are in scope. (Possibly) build a new overload set containing only + // those declarations that are in scope. + OverloadedFunctionDecl *NewOvl = 0; + bool FoundInScope = false; + for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), + FEnd = Ovl->function_end(); + F != FEnd; ++F) { + NamedDecl *FD = F->get(); + if (!isDeclInScope(FD, Ctx, S)) { + if (!NewOvl && F != Ovl->function_begin()) { + NewOvl = OverloadedFunctionDecl::Create(Context, + F->get()->getDeclContext(), + F->get()->getDeclName()); + D = NewOvl; + for (OverloadedFunctionDecl::function_iterator + First = Ovl->function_begin(); + First != F; ++First) + NewOvl->addOverload(*First); + } + } else { + FoundInScope = true; + if (NewOvl) + NewOvl->addOverload(*F); + } + } + + return FoundInScope; + } + + return IdResolver.isDeclInScope(D, Ctx, Context, S); +} + void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (S->decl_empty()) return; assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && - "Scope shouldn't contain decls!"); + "Scope shouldn't contain decls!"); for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); I != E; ++I) { @@ -368,6 +407,12 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (!D->getDeclName()) continue; + // Diagnose unused variables in this scope. + if (!D->isUsed() && !D->hasAttr<UnusedAttr>() && isa<VarDecl>(D) && + !isa<ParmVarDecl>(D) && !isa<ImplicitParamDecl>(D) && + D->getDeclContext()->isFunctionOrMethod()) + Diag(D->getLocation(), diag::warn_unused_variable) << D->getDeclName(); + // Remove this name from our lexical scope. IdResolver.RemoveDecl(D); } @@ -378,8 +423,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) { // The third "scope" argument is 0 since we aren't enabling lazy built-in // creation from this context. - NamedDecl *IDecl = LookupName(TUScope, Id, LookupOrdinaryName); - + NamedDecl *IDecl = LookupSingleName(TUScope, Id, LookupOrdinaryName); + return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl); } @@ -392,7 +437,7 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) { /// struct S6 { /// enum { BAR } e; /// }; -/// +/// /// void test_S6() { /// struct S6 a; /// a.e = BAR; @@ -408,7 +453,7 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) { /// contain non-field names. Scope *Sema::getNonFieldDeclScope(Scope *S) { while (((S->getFlags() & Scope::DeclScope) == 0) || - (S->getEntity() && + (S->getEntity() && ((DeclContext *)S->getEntity())->isTransparentContext()) || (S->isClassScope() && !getLangOptions().CPlusPlus)) S = S->getParent(); @@ -418,9 +463,9 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) { void Sema::InitBuiltinVaListType() { if (!Context.getBuiltinVaListType().isNull()) return; - + IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list"); - NamedDecl *VaDecl = LookupName(TUScope, VaIdent, LookupOrdinaryName); + NamedDecl *VaDecl = LookupSingleName(TUScope, VaIdent, LookupOrdinaryName); TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl); Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef)); } @@ -438,17 +483,23 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, InitBuiltinVaListType(); ASTContext::GetBuiltinTypeError Error; - QualType R = Context.GetBuiltinType(BID, Error); + QualType R = Context.GetBuiltinType(BID, Error); switch (Error) { case ASTContext::GE_None: // Okay break; - case ASTContext::GE_Missing_FILE: + case ASTContext::GE_Missing_stdio: if (ForRedeclaration) Diag(Loc, diag::err_implicit_decl_requires_stdio) << Context.BuiltinInfo.GetName(BID); return 0; + + case ASTContext::GE_Missing_setjmp: + if (ForRedeclaration) + Diag(Loc, diag::err_implicit_decl_requires_setjmp) + << Context.BuiltinInfo.GetName(BID); + return 0; } if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) { @@ -465,7 +516,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, FunctionDecl *New = FunctionDecl::Create(Context, Context.getTranslationUnitDecl(), - Loc, II, R, + Loc, II, R, /*DInfo=*/0, FunctionDecl::Extern, false, /*hasPrototype=*/true); New->setImplicit(); @@ -476,12 +527,13 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, llvm::SmallVector<ParmVarDecl*, 16> Params; for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0, - FT->getArgType(i), VarDecl::None, 0)); + FT->getArgType(i), /*DInfo=*/0, + VarDecl::None, 0)); New->setParams(Context, Params.data(), Params.size()); } - - AddKnownFunctionAttributes(New); - + + AddKnownFunctionAttributes(New); + // TUScope is the translation-unit scope to insert this function into. // FIXME: This is hideous. We need to teach PushOnScopeChains to // relate Scopes to DeclContexts, and probably eliminate CurContext @@ -493,18 +545,6 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, return New; } -/// GetStdNamespace - This method gets the C++ "std" namespace. This is where -/// everything from the standard library is defined. -NamespaceDecl *Sema::GetStdNamespace() { - if (!StdNamespace) { - IdentifierInfo *StdIdent = &PP.getIdentifierTable().get("std"); - DeclContext *Global = Context.getTranslationUnitDecl(); - Decl *Std = LookupQualifiedName(Global, StdIdent, LookupNamespaceName); - StdNamespace = dyn_cast_or_null<NamespaceDecl>(Std); - } - return StdNamespace; -} - /// 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 @@ -515,25 +555,26 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { // don't bother doing any merging checks. if (New->isInvalidDecl() || OldD->isInvalidDecl()) return New->setInvalidDecl(); - - bool objc_types = false; - + // Allow multiple definitions for ObjC built-in typedefs. // FIXME: Verify the underlying types are equivalent! if (getLangOptions().ObjC1) { const IdentifierInfo *TypeID = New->getIdentifier(); switch (TypeID->getLength()) { default: break; - case 2: + case 2: if (!TypeID->isStr("id")) break; - Context.setObjCIdType(Context.getTypeDeclType(New)); - objc_types = true; - break; + Context.ObjCIdRedefinitionType = New->getUnderlyingType(); + // Install the built-in type for 'id', ignoring the current definition. + New->setTypeForDecl(Context.getObjCIdType().getTypePtr()); + return; case 5: if (!TypeID->isStr("Class")) break; - Context.setObjCClassType(Context.getTypeDeclType(New)); + Context.ObjCClassRedefinitionType = New->getUnderlyingType(); + // Install the built-in type for 'Class', ignoring the current definition. + New->setTypeForDecl(Context.getObjCClassType().getTypePtr()); return; case 3: if (!TypeID->isStr("SEL")) @@ -551,14 +592,14 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { // Verify the old decl was also a type. TypeDecl *Old = dyn_cast<TypeDecl>(OldD); if (!Old) { - Diag(New->getLocation(), diag::err_redefinition_different_kind) + Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); if (OldD->getLocation().isValid()) Diag(OldD->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); } - // Determine the "old" type we'll use for checking and diagnostics. + // Determine the "old" type we'll use for checking and diagnostics. QualType OldType; if (TypedefDecl *OldTypedef = dyn_cast<TypedefDecl>(Old)) OldType = OldTypedef->getUnderlyingType(); @@ -568,8 +609,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { // If the typedef types are not identical, reject them in all languages and // with any extensions enabled. - if (OldType != New->getUnderlyingType() && - Context.getCanonicalType(OldType) != + if (OldType != New->getUnderlyingType() && + Context.getCanonicalType(OldType) != Context.getCanonicalType(New->getUnderlyingType())) { Diag(New->getLocation(), diag::err_redefinition_different_typedef) << New->getUnderlyingType() << OldType; @@ -577,8 +618,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); } - - if (objc_types || getLangOptions().Microsoft) + + if (getLangOptions().Microsoft) return; // C++ [dcl.typedef]p2: @@ -602,7 +643,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { (Context.getSourceManager().isInSystemHeader(Old->getLocation()) || Context.getSourceManager().isInSystemHeader(New->getLocation()))) return; - + Diag(New->getLocation(), diag::warn_redefinition_of_typedef) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); @@ -611,7 +652,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { /// DeclhasAttr - returns true if decl Declaration already has the target /// attribute. -static bool +static bool DeclHasAttr(const Decl *decl, const Attr *target) { for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext()) if (attr->getKind() == target->getKind()) @@ -651,15 +692,15 @@ struct GNUCompatibleParamWarning { /// /// Returns true if there was an error, false otherwise. bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { - assert(!isa<OverloadedFunctionDecl>(OldD) && + assert(!isa<OverloadedFunctionDecl>(OldD) && "Cannot merge with an overloaded function declaration"); // Verify the old decl was also a function. FunctionDecl *Old = 0; - if (FunctionTemplateDecl *OldFunctionTemplate + if (FunctionTemplateDecl *OldFunctionTemplate = dyn_cast<FunctionTemplateDecl>(OldD)) Old = OldFunctionTemplate->getTemplatedDecl(); - else + else Old = dyn_cast<FunctionDecl>(OldD); if (!Old) { Diag(New->getLocation(), diag::err_redefinition_different_kind) @@ -675,12 +716,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { PrevDiag = diag::note_previous_definition; else if (Old->isImplicit()) PrevDiag = diag::note_previous_implicit_declaration; - else + else PrevDiag = diag::note_previous_declaration; - + QualType OldQType = Context.getCanonicalType(Old->getType()); QualType NewQType = Context.getCanonicalType(New->getType()); - + if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) && New->getStorageClass() == FunctionDecl::Static && Old->getStorageClass() != FunctionDecl::Static) { @@ -693,11 +734,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { if (getLangOptions().CPlusPlus) { // (C++98 13.1p2): // Certain function declarations cannot be overloaded: - // -- Function declarations that differ only in the return type + // -- Function declarations that differ only in the return type // cannot be overloaded. - QualType OldReturnType + QualType OldReturnType = cast<FunctionType>(OldQType.getTypePtr())->getResultType(); - QualType NewReturnType + QualType NewReturnType = cast<FunctionType>(NewQType.getTypePtr())->getResultType(); if (OldReturnType != NewReturnType) { Diag(New->getLocation(), diag::err_ovl_diff_return_type); @@ -707,11 +748,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); - if (OldMethod && NewMethod && - OldMethod->getLexicalDeclContext() == - NewMethod->getLexicalDeclContext()) { - // -- Member function declarations with the same name and the - // same parameter types cannot be overloaded if any of them + if (OldMethod && NewMethod && !NewMethod->getFriendObjectKind() && + NewMethod->getLexicalDeclContext()->isRecord()) { + // -- Member function declarations with the same name and the + // same parameter types cannot be overloaded if any of them // is a static member function declaration. if (OldMethod->isStatic() || NewMethod->isStatic()) { Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member); @@ -732,7 +772,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { NewDiag = diag::err_conv_function_redeclared; else NewDiag = diag::err_member_redeclared; - + Diag(New->getLocation(), NewDiag); Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); } @@ -750,8 +790,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // duplicate function decls like "void f(int); void f(enum X);" properly. if (!getLangOptions().CPlusPlus && Context.typesAreCompatible(OldQType, NewQType)) { - const FunctionType *OldFuncType = OldQType->getAsFunctionType(); - const FunctionType *NewFuncType = NewQType->getAsFunctionType(); + const FunctionType *OldFuncType = OldQType->getAs<FunctionType>(); + const FunctionType *NewFuncType = NewQType->getAs<FunctionType>(); const FunctionProtoType *OldProto = 0; if (isa<FunctionNoProtoType>(NewFuncType) && (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) { @@ -769,20 +809,20 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // Synthesize a parameter for each argument type. llvm::SmallVector<ParmVarDecl*, 16> Params; - for (FunctionProtoType::arg_type_iterator - ParamType = OldProto->arg_type_begin(), + for (FunctionProtoType::arg_type_iterator + ParamType = OldProto->arg_type_begin(), ParamEnd = OldProto->arg_type_end(); ParamType != ParamEnd; ++ParamType) { ParmVarDecl *Param = ParmVarDecl::Create(Context, New, SourceLocation(), 0, - *ParamType, VarDecl::None, - 0); + *ParamType, /*DInfo=*/0, + VarDecl::None, 0); Param->setImplicit(); Params.push_back(Param); } New->setParams(Context, Params.data(), Params.size()); - } + } return MergeCompatibleFunctionDecls(New, Old); } @@ -800,29 +840,29 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // C99 6.9.1p8. if (!getLangOptions().CPlusPlus && Old->hasPrototype() && !New->hasPrototype() && - New->getType()->getAsFunctionProtoType() && + New->getType()->getAs<FunctionProtoType>() && Old->getNumParams() == New->getNumParams()) { llvm::SmallVector<QualType, 16> ArgTypes; llvm::SmallVector<GNUCompatibleParamWarning, 16> Warnings; - const FunctionProtoType *OldProto - = Old->getType()->getAsFunctionProtoType(); - const FunctionProtoType *NewProto - = New->getType()->getAsFunctionProtoType(); - + const FunctionProtoType *OldProto + = Old->getType()->getAs<FunctionProtoType>(); + const FunctionProtoType *NewProto + = New->getType()->getAs<FunctionProtoType>(); + // Determine whether this is the GNU C extension. QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(), NewProto->getResultType()); bool LooseCompatible = !MergedReturn.isNull(); - for (unsigned Idx = 0, End = Old->getNumParams(); + for (unsigned Idx = 0, End = Old->getNumParams(); LooseCompatible && Idx != End; ++Idx) { ParmVarDecl *OldParm = Old->getParamDecl(Idx); ParmVarDecl *NewParm = New->getParamDecl(Idx); - if (Context.typesAreCompatible(OldParm->getType(), + if (Context.typesAreCompatible(OldParm->getType(), NewProto->getArgType(Idx))) { ArgTypes.push_back(NewParm->getType()); } else if (Context.typesAreCompatible(OldParm->getType(), NewParm->getType())) { - GNUCompatibleParamWarning Warn + GNUCompatibleParamWarning Warn = { OldParm, NewParm, NewProto->getArgType(Idx) }; Warnings.push_back(Warn); ArgTypes.push_back(NewParm->getType()); @@ -836,7 +876,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { diag::ext_param_promoted_not_compatible_with_prototype) << Warnings[Warn].PromotedType << Warnings[Warn].OldParm->getType(); - Diag(Warnings[Warn].OldParm->getLocation(), + Diag(Warnings[Warn].OldParm->getLocation(), diag::note_previous_declaration); } @@ -851,7 +891,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // A function that has already been declared has been redeclared or defined // with a different type- show appropriate diagnostic - if (unsigned BuiltinID = Old->getBuiltinID(Context)) { + if (unsigned BuiltinID = Old->getBuiltinID()) { // The user has declared a builtin function with an incompatible // signature. if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { @@ -876,7 +916,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { } /// \brief Completes the merge of two function declarations that are -/// known to be compatible. +/// known to be compatible. /// /// This routine handles the merging of attributes and other /// properties of function declarations form the old declaration to @@ -889,25 +929,10 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { MergeAttributes(New, Old, Context); // Merge the storage class. - if (Old->getStorageClass() != FunctionDecl::Extern) + if (Old->getStorageClass() != FunctionDecl::Extern && + Old->getStorageClass() != FunctionDecl::None) New->setStorageClass(Old->getStorageClass()); - // Merge "inline" - if (Old->isInline()) - New->setInline(true); - - // If this function declaration by itself qualifies as a C99 inline - // definition (C99 6.7.4p6), but the previous definition did not, - // then the function is not a C99 inline definition. - if (New->isC99InlineDefinition() && !Old->isC99InlineDefinition()) - New->setC99InlineDefinition(false); - else if (Old->isC99InlineDefinition() && !New->isC99InlineDefinition()) { - // Mark all preceding definitions as not being C99 inline definitions. - for (const FunctionDecl *Prev = Old; Prev; - Prev = Prev->getPreviousDeclaration()) - const_cast<FunctionDecl *>(Prev)->setC99InlineDefinition(false); - } - // Merge "pure" flag. if (Old->isPure()) New->setPure(); @@ -915,7 +940,7 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { // Merge the "deleted" flag. if (Old->isDeleted()) New->setDeleted(); - + if (getLangOptions().CPlusPlus) return MergeCXXFunctionDecl(New, Old); @@ -926,16 +951,16 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { /// and scope as a previous declaration 'Old'. Figure out how to resolve this /// situation, merging decls or emitting diagnostics as appropriate. /// -/// Tentative definition rules (C99 6.9.2p2) are checked by -/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative +/// Tentative definition rules (C99 6.9.2p2) are checked by +/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative /// definitions here, since the initializer hasn't been attached. -/// +/// void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { // If either decl is invalid, make sure the new one is marked invalid and // don't do any other checking. if (New->isInvalidDecl() || OldD->isInvalidDecl()) return New->setInvalidDecl(); - + // Verify the old decl was also a variable. VarDecl *Old = dyn_cast<VarDecl>(OldD); if (!Old) { @@ -952,11 +977,24 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { if (getLangOptions().CPlusPlus) { if (Context.hasSameType(New->getType(), Old->getType())) MergedT = New->getType(); + // C++ [basic.types]p7: + // [...] The declared type of an array object might be an array of + // unknown size and therefore be incomplete at one point in a + // translation unit and complete later on; [...] + else if (Old->getType()->isIncompleteArrayType() && + New->getType()->isArrayType()) { + CanQual<ArrayType> OldArray + = Context.getCanonicalType(Old->getType())->getAs<ArrayType>(); + CanQual<ArrayType> NewArray + = Context.getCanonicalType(New->getType())->getAs<ArrayType>(); + if (OldArray->getElementType() == NewArray->getElementType()) + MergedT = New->getType(); + } } else { MergedT = Context.mergeTypes(New->getType(), Old->getType()); } if (MergedT.isNull()) { - Diag(New->getLocation(), diag::err_redefinition_different_type) + Diag(New->getLocation(), diag::err_redefinition_different_type) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -970,7 +1008,7 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); } - // C99 6.2.2p4: + // C99 6.2.2p4: // For an identifier declared with the storage-class specifier // extern in a scope in which a prior declaration of that // identifier is visible,23) if the prior declaration specifies @@ -989,7 +1027,7 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { } // Variables with external linkage are analyzed in FinalizeDeclaratorGroup. - + // FIXME: The test for external storage here seems wrong? We still // need to check for mismatches. if (!New->hasExternalStorage() && !New->isFileVarDecl() && @@ -1013,6 +1051,214 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { New->setPreviousDeclaration(Old); } +/// CheckFallThrough - Check that we don't fall off the end of a +/// Statement that should return a value. +/// +/// \returns AlwaysFallThrough iff we always fall off the end of the statement, +/// MaybeFallThrough iff we might or might not fall off the end and +/// NeverFallThrough iff we never fall off the end of the statement. We assume +/// that functions not marked noreturn will return. +Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) { + llvm::OwningPtr<CFG> cfg (CFG::buildCFG(Root, &Context)); + + // FIXME: They should never return 0, fix that, delete this code. + if (cfg == 0) + return NeverFallThrough; + // The CFG leaves in dead things, and we don't want to dead code paths to + // confuse us, so we mark all live things first. + std::queue<CFGBlock*> workq; + llvm::BitVector live(cfg->getNumBlockIDs()); + // Prep work queue + workq.push(&cfg->getEntry()); + // Solve + while (!workq.empty()) { + CFGBlock *item = workq.front(); + workq.pop(); + live.set(item->getBlockID()); + for (CFGBlock::succ_iterator I=item->succ_begin(), + E=item->succ_end(); + I != E; + ++I) { + if ((*I) && !live[(*I)->getBlockID()]) { + live.set((*I)->getBlockID()); + workq.push(*I); + } + } + } + + // Now we know what is live, we check the live precessors of the exit block + // and look for fall through paths, being careful to ignore normal returns, + // and exceptional paths. + bool HasLiveReturn = false; + bool HasFakeEdge = false; + bool HasPlainEdge = false; + for (CFGBlock::succ_iterator I=cfg->getExit().pred_begin(), + E = cfg->getExit().pred_end(); + I != E; + ++I) { + CFGBlock& B = **I; + if (!live[B.getBlockID()]) + continue; + if (B.size() == 0) { + // A labeled empty statement, or the entry block... + HasPlainEdge = true; + continue; + } + Stmt *S = B[B.size()-1]; + if (isa<ReturnStmt>(S)) { + HasLiveReturn = true; + continue; + } + if (isa<ObjCAtThrowStmt>(S)) { + HasFakeEdge = true; + continue; + } + if (isa<CXXThrowExpr>(S)) { + HasFakeEdge = true; + continue; + } + bool NoReturnEdge = false; + if (CallExpr *C = dyn_cast<CallExpr>(S)) { + Expr *CEE = C->getCallee()->IgnoreParenCasts(); + if (CEE->getType().getNoReturnAttr()) { + NoReturnEdge = true; + HasFakeEdge = true; + } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) { + if (FD->hasAttr<NoReturnAttr>()) { + NoReturnEdge = true; + HasFakeEdge = true; + } + } + } + } + // FIXME: Add noreturn message sends. + if (NoReturnEdge == false) + HasPlainEdge = true; + } + if (!HasPlainEdge) + return NeverFallThrough; + if (HasFakeEdge || HasLiveReturn) + return MaybeFallThrough; + // This says AlwaysFallThrough for calls to functions that are not marked + // noreturn, that don't return. If people would like this warning to be more + // accurate, such functions should be marked as noreturn. + return AlwaysFallThrough; +} + +/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a +/// function that should return a value. Check that we don't fall off the end +/// of a noreturn function. We assume that functions and blocks not marked +/// noreturn will return. +void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) { + // FIXME: Would be nice if we had a better way to control cascading errors, + // but for now, avoid them. The problem is that when Parse sees: + // int foo() { return a; } + // The return is eaten and the Sema code sees just: + // int foo() { } + // which this code would then warn about. + if (getDiagnostics().hasErrorOccurred()) + return; + bool ReturnsVoid = false; + bool HasNoReturn = false; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // If the result type of the function is a dependent type, we don't know + // whether it will be void or not, so don't + if (FD->getResultType()->isDependentType()) + return; + if (FD->getResultType()->isVoidType()) + ReturnsVoid = true; + if (FD->hasAttr<NoReturnAttr>()) + HasNoReturn = true; + } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { + if (MD->getResultType()->isVoidType()) + ReturnsVoid = true; + if (MD->hasAttr<NoReturnAttr>()) + HasNoReturn = true; + } + + // Short circuit for compilation speed. + if ((Diags.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function) + == Diagnostic::Ignored || ReturnsVoid) + && (Diags.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr) + == Diagnostic::Ignored || !HasNoReturn) + && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block) + == Diagnostic::Ignored || !ReturnsVoid)) + return; + // FIXME: Function try block + if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { + switch (CheckFallThrough(Body)) { + case MaybeFallThrough: + if (HasNoReturn) + Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function); + else if (!ReturnsVoid) + Diag(Compound->getRBracLoc(),diag::warn_maybe_falloff_nonvoid_function); + break; + case AlwaysFallThrough: + if (HasNoReturn) + Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function); + else if (!ReturnsVoid) + Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function); + break; + case NeverFallThrough: + if (ReturnsVoid) + Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function); + break; + } + } +} + +/// CheckFallThroughForBlock - Check that we don't fall off the end of a block +/// that should return a value. Check that we don't fall off the end of a +/// noreturn block. We assume that functions and blocks not marked noreturn +/// will return. +void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) { + // FIXME: Would be nice if we had a better way to control cascading errors, + // but for now, avoid them. The problem is that when Parse sees: + // int foo() { return a; } + // The return is eaten and the Sema code sees just: + // int foo() { } + // which this code would then warn about. + if (getDiagnostics().hasErrorOccurred()) + return; + bool ReturnsVoid = false; + bool HasNoReturn = false; + if (const FunctionType *FT = BlockTy->getPointeeType()->getAs<FunctionType>()) { + if (FT->getResultType()->isVoidType()) + ReturnsVoid = true; + if (FT->getNoReturnAttr()) + HasNoReturn = true; + } + + // Short circuit for compilation speed. + if (ReturnsVoid + && !HasNoReturn + && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block) + == Diagnostic::Ignored || !ReturnsVoid)) + return; + // FIXME: Funtion try block + if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { + switch (CheckFallThrough(Body)) { + case MaybeFallThrough: + if (HasNoReturn) + Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr); + else if (!ReturnsVoid) + Diag(Compound->getRBracLoc(), diag::err_maybe_falloff_nonvoid_block); + break; + case AlwaysFallThrough: + if (HasNoReturn) + Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr); + else if (!ReturnsVoid) + Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block); + break; + case NeverFallThrough: + if (ReturnsVoid) + Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block); + break; + } + } +} + /// CheckParmsForFunctionDef - Check that the parameters of the given /// function are appropriate for the definition of a function. This /// takes care of any checks that cannot be performed on the @@ -1034,10 +1280,10 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) { Param->setInvalidDecl(); HasInvalidParm = true; } - + // C99 6.9.1p5: If the declarator includes a parameter type list, the // declaration of each parameter shall include an identifier. - if (Param->getIdentifier() == 0 && + if (Param->getIdentifier() == 0 && !Param->isImplicit() && !getLangOptions().CPlusPlus) Diag(Param->getLocation(), diag::err_parameter_name_omitted); @@ -1056,17 +1302,31 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { // FIXME: Warn on useless const/volatile // FIXME: Warn on useless static/extern/typedef/private_extern/mutable // FIXME: Warn on useless attributes + Decl *TagD = 0; TagDecl *Tag = 0; if (DS.getTypeSpecType() == DeclSpec::TST_class || DS.getTypeSpecType() == DeclSpec::TST_struct || DS.getTypeSpecType() == DeclSpec::TST_union || DS.getTypeSpecType() == DeclSpec::TST_enum) { - if (!DS.getTypeRep()) // We probably had an error + TagD = static_cast<Decl *>(DS.getTypeRep()); + + if (!TagD) // We probably had an error return DeclPtrTy(); - Tag = dyn_cast<TagDecl>(static_cast<Decl *>(DS.getTypeRep())); + // Note that the above type specs guarantee that the + // type rep is a Decl, whereas in many of the others + // it's a Type. + Tag = dyn_cast<TagDecl>(TagD); } + if (DS.isFriendSpecified()) { + // If we're dealing with a class template decl, assume that the + // template routines are handling it. + if (TagD && isa<ClassTemplateDecl>(TagD)) + return DeclPtrTy(); + return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0)); + } + if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) { if (!Record->getDeclName() && Record->isDefinition() && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { @@ -1084,8 +1344,8 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { if (Record->getDeclName() && getLangOptions().Microsoft) return DeclPtrTy::make(Tag); } - - if (!DS.isMissingDeclaratorOk() && + + if (!DS.isMissingDeclaratorOk() && DS.getTypeSpecType() != DeclSpec::TST_error) { // Warn about typedefs of enums without names, since this is an // extension in both Microsoft an GNU. @@ -1100,7 +1360,7 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { << DS.getSourceRange(); return DeclPtrTy(); } - + return DeclPtrTy::make(Tag); } @@ -1127,14 +1387,16 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, FEnd = AnonRecord->field_end(); F != FEnd; ++F) { if ((*F)->getDeclName()) { - NamedDecl *PrevDecl = LookupQualifiedName(Owner, (*F)->getDeclName(), - LookupOrdinaryName, true); + LookupResult R; + LookupQualifiedName(R, Owner, (*F)->getDeclName(), + LookupOrdinaryName, true); + NamedDecl *PrevDecl = R.getAsSingleDecl(Context); if (PrevDecl && !isa<TagDecl>(PrevDecl)) { // C++ [class.union]p2: // The names of the members of an anonymous union shall be // distinct from the names of any other entity in the // scope in which the anonymous union is declared. - unsigned diagKind + unsigned diagKind = AnonRecord->isUnion()? diag::err_anonymous_union_member_redecl : diag::err_anonymous_struct_member_redecl; Diag((*F)->getLocation(), diagKind) @@ -1152,10 +1414,10 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, IdResolver.AddDecl(*F); } } else if (const RecordType *InnerRecordType - = (*F)->getType()->getAsRecordType()) { + = (*F)->getType()->getAs<RecordType>()) { RecordDecl *InnerRecord = InnerRecordType->getDecl(); if (InnerRecord->isAnonymousStructOrUnion()) - Invalid = Invalid || + Invalid = Invalid || InjectAnonymousStructOrUnionMembers(S, Owner, InnerRecord); } } @@ -1166,7 +1428,7 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, /// ActOnAnonymousStructOrUnion - Handle the declaration of an /// anonymous structure or union. Anonymous unions are a C++ feature /// (C++ [class.union]) and a GNU C extension; anonymous structures -/// are a GNU C and GNU C++ extension. +/// are a GNU C and GNU C++ extension. Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, RecordDecl *Record) { DeclContext *Owner = Record->getDeclContext(); @@ -1176,40 +1438,42 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Diag(Record->getLocation(), diag::ext_anonymous_union); else if (!Record->isUnion()) Diag(Record->getLocation(), diag::ext_anonymous_struct); - + // C and C++ require different kinds of checks for anonymous // structs/unions. bool Invalid = false; if (getLangOptions().CPlusPlus) { const char* PrevSpec = 0; + unsigned DiagID; // C++ [class.union]p3: // Anonymous unions declared in a named namespace or in the // global namespace shall be declared static. if (DS.getStorageClassSpec() != DeclSpec::SCS_static && (isa<TranslationUnitDecl>(Owner) || - (isa<NamespaceDecl>(Owner) && + (isa<NamespaceDecl>(Owner) && cast<NamespaceDecl>(Owner)->getDeclName()))) { Diag(Record->getLocation(), diag::err_anonymous_union_not_static); Invalid = true; // Recover by adding 'static'. - DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(), PrevSpec); - } + DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(), + PrevSpec, DiagID); + } // C++ [class.union]p3: // A storage class is not allowed in a declaration of an // anonymous union in a class scope. else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified && isa<RecordDecl>(Owner)) { - Diag(DS.getStorageClassSpecLoc(), + Diag(DS.getStorageClassSpecLoc(), diag::err_anonymous_union_with_storage_spec); Invalid = true; // Recover by removing the storage specifier. DS.SetStorageClassSpec(DeclSpec::SCS_unspecified, SourceLocation(), - PrevSpec); + PrevSpec, DiagID); } - // C++ [class.union]p2: + // C++ [class.union]p2: // The member-specification of an anonymous union shall only // define non-static data members. [Note: nested types and // functions cannot be declared within an anonymous union. ] @@ -1255,7 +1519,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Invalid = true; } } - } + } if (!Record->isUnion() && !Owner->isRecord()) { Diag(Record->getLocation(), diag::err_anonymous_struct_not_member) @@ -1263,12 +1527,14 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Invalid = true; } - // Create a declaration for this anonymous struct/union. + // Create a declaration for this anonymous struct/union. NamedDecl *Anon = 0; if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) { Anon = FieldDecl::Create(Context, OwningClass, Record->getLocation(), - /*IdentifierInfo=*/0, + /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), + // FIXME: Type source info. + /*DInfo=*/0, /*BitWidth=*/0, /*Mutable=*/false); Anon->setAccess(AS_public); if (getLangOptions().CPlusPlus) @@ -1293,9 +1559,11 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, } Anon = VarDecl::Create(Context, Owner, Record->getLocation(), - /*IdentifierInfo=*/0, + /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), - SC, DS.getSourceRange().getBegin()); + // FIXME: Type source info. + /*DInfo=*/0, + SC); } Anon->setImplicit(); @@ -1315,7 +1583,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // members of this anonymous struct/union type, because otherwise // the members could be injected twice: once by DeclContext when it // builds its lookup table, and once by - // InjectAnonymousStructOrUnionMembers. + // InjectAnonymousStructOrUnionMembers. Record->setAnonymousStructOrUnion(true); if (Invalid) @@ -1338,28 +1606,39 @@ DeclarationName Sema::GetNameForDeclarator(Declarator &D) { return DeclarationName(D.getIdentifier()); case Declarator::DK_Constructor: { - QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType()); - Ty = Context.getCanonicalType(Ty); - return Context.DeclarationNames.getCXXConstructorName(Ty); + QualType Ty = GetTypeFromParser(D.getDeclaratorIdType()); + return Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(Ty)); } case Declarator::DK_Destructor: { - QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType()); - Ty = Context.getCanonicalType(Ty); - return Context.DeclarationNames.getCXXDestructorName(Ty); + QualType Ty = GetTypeFromParser(D.getDeclaratorIdType()); + return Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalType(Ty)); } case Declarator::DK_Conversion: { // FIXME: We'd like to keep the non-canonical type for diagnostics! - QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType()); - Ty = Context.getCanonicalType(Ty); - return Context.DeclarationNames.getCXXConversionFunctionName(Ty); + QualType Ty = GetTypeFromParser(D.getDeclaratorIdType()); + return Context.DeclarationNames.getCXXConversionFunctionName( + Context.getCanonicalType(Ty)); } case Declarator::DK_Operator: assert(D.getIdentifier() == 0 && "operator names have no identifier"); return Context.DeclarationNames.getCXXOperatorName( D.getOverloadedOperator()); + + case Declarator::DK_TemplateId: { + TemplateName Name + = TemplateName::getFromVoidPointer(D.getTemplateId()->Template); + if (TemplateDecl *Template = Name.getAsTemplateDecl()) + return Template->getDeclName(); + if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl()) + return Ovl->getDeclName(); + + return DeclarationName(); + } } assert(false && "Unknown name kind"); @@ -1389,8 +1668,8 @@ static bool isNearlyMatchingFunction(ASTContext &Context, return true; } -Sema::DeclPtrTy -Sema::HandleDeclarator(Scope *S, Declarator &D, +Sema::DeclPtrTy +Sema::HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition) { DeclarationName Name = GetNameForDeclarator(D); @@ -1404,18 +1683,44 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, << D.getDeclSpec().getSourceRange() << D.getSourceRange(); return DeclPtrTy(); } - + // 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->getFlags() & Scope::TemplateParamScope) != 0) S = S->getParent(); - + + // If this is an out-of-line definition of a member of a class template + // or class template partial specialization, we may need to rebuild the + // type specifier in the declarator. See RebuildTypeInCurrentInstantiation() + // for more information. + // FIXME: cope with decltype(expr) and typeof(expr) once the rebuilder can + // handle expressions properly. + DeclSpec &DS = const_cast<DeclSpec&>(D.getDeclSpec()); + if (D.getCXXScopeSpec().isSet() && !D.getCXXScopeSpec().isInvalid() && + isDependentScopeSpecifier(D.getCXXScopeSpec()) && + (DS.getTypeSpecType() == DeclSpec::TST_typename || + DS.getTypeSpecType() == DeclSpec::TST_typeofType || + DS.getTypeSpecType() == DeclSpec::TST_typeofExpr || + DS.getTypeSpecType() == DeclSpec::TST_decltype)) { + if (DeclContext *DC = computeDeclContext(D.getCXXScopeSpec(), true)) { + // FIXME: Preserve type source info. + QualType T = GetTypeFromParser(DS.getTypeRep()); + EnterDeclaratorContext(S, DC); + T = RebuildTypeInCurrentInstantiation(T, D.getIdentifierLoc(), Name); + ExitDeclaratorContext(S); + if (T.isNull()) + return DeclPtrTy(); + DS.UpdateTypeRep(T.getAsOpaquePtr()); + } + } + DeclContext *DC; NamedDecl *PrevDecl; NamedDecl *New; - QualType R = GetTypeForDeclarator(D, S); + DeclaratorInfo *DInfo = 0; + QualType R = GetTypeForDeclarator(D, S, &DInfo); // See if this is a redefinition of a variable in the same scope. if (D.getCXXScopeSpec().isInvalid()) { @@ -1431,20 +1736,43 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) /* Do nothing*/; else if (R->isFunctionType()) { - if (CurContext->isFunctionOrMethod()) + if (CurContext->isFunctionOrMethod() || + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) NameKind = LookupRedeclarationWithLinkage; } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) NameKind = LookupRedeclarationWithLinkage; + else if (CurContext->getLookupContext()->isTranslationUnit() && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) + NameKind = LookupRedeclarationWithLinkage; DC = CurContext; - PrevDecl = LookupName(S, Name, NameKind, true, - D.getDeclSpec().getStorageClassSpec() != - DeclSpec::SCS_static, - D.getIdentifierLoc()); + LookupResult R; + LookupName(R, S, Name, NameKind, true, + NameKind == LookupRedeclarationWithLinkage, + D.getIdentifierLoc()); + PrevDecl = R.getAsSingleDecl(Context); } else { // Something like "int foo::x;" - DC = computeDeclContext(D.getCXXScopeSpec()); - // FIXME: RequireCompleteDeclContext(D.getCXXScopeSpec()); ? - PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true); + DC = computeDeclContext(D.getCXXScopeSpec(), true); + + if (!DC) { + // If we could not compute the declaration context, it's because the + // declaration context is dependent but does not refer to a class, + // class template, or class template partial specialization. Complain + // and return early, to avoid the coming semantic disaster. + Diag(D.getIdentifierLoc(), + diag::err_template_qualified_declarator_no_match) + << (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep() + << D.getCXXScopeSpec().getRange(); + return DeclPtrTy(); + } + + if (!DC->isDependentContext() && + RequireCompleteDeclContext(D.getCXXScopeSpec())) + return DeclPtrTy(); + + LookupResult Res; + LookupQualifiedName(Res, DC, Name, LookupOrdinaryName, true); + PrevDecl = Res.getAsSingleDecl(Context); // C++ 7.3.1.2p2: // Members (including explicit specializations of templates) of a named @@ -1467,11 +1795,11 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, // // In this case, PrevDecl will point to the overload set // containing the two f's declared in X, but neither of them - // matches. + // matches. // First check whether we named the global scope. if (isa<TranslationUnitDecl>(DC)) { - Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope) + Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope) << Name << D.getCXXScopeSpec().getRange(); } else if (!CurContext->Encloses(DC)) { // The qualifying scope doesn't enclose the original declaration. @@ -1480,7 +1808,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, SourceRange R = D.getCXXScopeSpec().getRange(); if (isa<FunctionDecl>(CurContext)) Diag(L, diag::err_invalid_declarator_in_function) << Name << R; - else + else Diag(L, diag::err_invalid_declarator_scope) << Name << cast<NamedDecl>(DC) << R; D.setInvalidType(); @@ -1489,10 +1817,10 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. - if (!D.isInvalidType()) + if (!D.isInvalidType()) if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl)) D.setInvalidType(); - + // Just pretend that we didn't see the previous declaration. PrevDecl = 0; } @@ -1511,24 +1839,28 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, Diag(D.getIdentifierLoc(), diag::err_template_typedef); return DeclPtrTy(); } - - New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl, Redeclaration); + + New = ActOnTypedefDeclarator(S, D, DC, R, DInfo, PrevDecl, Redeclaration); } else if (R->isFunctionType()) { - New = ActOnFunctionDeclarator(S, D, DC, R, PrevDecl, + New = ActOnFunctionDeclarator(S, D, DC, R, DInfo, PrevDecl, move(TemplateParamLists), IsFunctionDefinition, Redeclaration); } else { - New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl, Redeclaration); + New = ActOnVariableDeclarator(S, D, DC, R, DInfo, PrevDecl, + move(TemplateParamLists), + Redeclaration); } if (New == 0) return DeclPtrTy(); - - // If this has an identifier and is not an invalid redeclaration, - // add it to the scope stack. - if (Name && !(Redeclaration && New->isInvalidDecl())) + + // If this has an identifier and is not an invalid redeclaration or + // function template specialization, add it to the scope stack. + if (Name && !(Redeclaration && New->isInvalidDecl()) && + !(isa<FunctionDecl>(New) && + cast<FunctionDecl>(New)->isFunctionTemplateSpecialization())) PushOnScopeChains(New, S); - + return DeclPtrTy::make(New); } @@ -1544,14 +1876,16 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, // constant expression folding, like struct {char x[(int)(char*)2];} SizeIsNegative = false; - if (const PointerType* PTy = dyn_cast<PointerType>(T)) { + QualifierCollector Qs; + const Type *Ty = Qs.strip(T); + + if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) { QualType Pointee = PTy->getPointeeType(); QualType FixedType = TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative); if (FixedType.isNull()) return FixedType; FixedType = Context.getPointerType(FixedType); - FixedType.setCVRQualifiers(T.getCVRQualifiers()); - return FixedType; + return Qs.apply(FixedType); } const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T); @@ -1560,7 +1894,7 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, // FIXME: We should probably handle this case if (VLATy->getElementType()->isVariablyModifiedType()) return QualType(); - + Expr::EvalResult EvalResult; if (!VLATy->getSizeExpr() || !VLATy->getSizeExpr()->Evaluate(EvalResult, Context) || @@ -1568,9 +1902,18 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, return QualType(); llvm::APSInt &Res = EvalResult.Val.getInt(); - if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned())) - return Context.getConstantArrayType(VLATy->getElementType(), - Res, ArrayType::Normal, 0); + if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned())) { + Expr* ArySizeExpr = VLATy->getSizeExpr(); + // FIXME: here we could "steal" (how?) ArySizeExpr from the VLA, + // so as to transfer ownership to the ConstantArrayWithExpr. + // Alternatively, we could "clone" it (how?). + // Since we don't know how to do things above, we just use the + // very same Expr*. + return Context.getConstantArrayWithExprType(VLATy->getElementType(), + Res, ArySizeExpr, + ArrayType::Normal, 0, + VLATy->getBracketsRange()); + } SizeIsNegative = true; return QualType(); @@ -1578,7 +1921,7 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, /// \brief Register the given locally-scoped external C declaration so /// that it can be found later for redeclarations -void +void Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl, Scope *S) { assert(ND->getLexicalDeclContext()->isFunctionOrMethod() && @@ -1609,21 +1952,22 @@ void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { // FIXME: We should probably indicate the identifier in question to avoid // confusion for constructs like "inline int a(), b;" if (D.getDeclSpec().isInlineSpecified()) - Diag(D.getDeclSpec().getInlineSpecLoc(), + Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function); if (D.getDeclSpec().isVirtualSpecified()) - Diag(D.getDeclSpec().getVirtualSpecLoc(), + Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_non_function); if (D.getDeclSpec().isExplicitSpecified()) - Diag(D.getDeclSpec().getExplicitSpecLoc(), + Diag(D.getDeclSpec().getExplicitSpecLoc(), diag::err_explicit_non_function); } NamedDecl* Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, Decl* PrevDecl, bool &Redeclaration) { + QualType R, DeclaratorInfo *DInfo, + NamedDecl* PrevDecl, bool &Redeclaration) { // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1). if (D.getCXXScopeSpec().isSet()) { Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator) @@ -1645,7 +1989,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, TypedefDecl *NewTD = ParseTypedefDecl(S, D, R); if (!NewTD) return 0; - + if (D.isInvalidType()) NewTD->setInvalidDecl(); @@ -1663,7 +2007,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType T = NewTD->getUnderlyingType(); if (T->isVariablyModifiedType()) { CurFunctionNeedsScopeChecking = true; - + if (S->getFnParent() == 0) { bool SizeIsNegative; QualType FixedTy = @@ -1682,6 +2026,19 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } } + + // If this is the C FILE type, notify the AST context. + if (IdentifierInfo *II = NewTD->getIdentifier()) + if (!NewTD->isInvalidDecl() && + NewTD->getDeclContext()->getLookupContext()->isTranslationUnit()) { + if (II->isStr("FILE")) + Context.setFILEDecl(NewTD); + else if (II->isStr("jmp_buf")) + Context.setjmp_bufDecl(NewTD); + else if (II->isStr("sigjmp_buf")) + Context.setsigjmp_bufDecl(NewTD); + } + return NewTD; } @@ -1697,13 +2054,13 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, /// /// \param PrevDecl the previous declaration found by name /// lookup -/// +/// /// \param DC the context in which the new declaration is being /// declared. /// /// \returns true if PrevDecl is an out-of-scope previous declaration /// for a new delcaration with the same name. -static bool +static bool isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, ASTContext &Context) { if (!PrevDecl) @@ -1737,10 +2094,10 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, OuterContext = OuterContext->getParent(); while (!PrevOuterContext->isFileContext()) PrevOuterContext = PrevOuterContext->getParent(); - + // The previous declaration is in a different namespace, so it // isn't the same function. - if (OuterContext->getPrimaryContext() != + if (OuterContext->getPrimaryContext() != PrevOuterContext->getPrimaryContext()) return false; } @@ -1752,7 +2109,9 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, NamedDecl* Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R,NamedDecl* PrevDecl, + QualType R, DeclaratorInfo *DInfo, + NamedDecl* PrevDecl, + MultiTemplateParamsArg TemplateParamLists, bool &Redeclaration) { DeclarationName Name = GetNameForDeclarator(D); @@ -1792,7 +2151,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, // 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) { - + // If this is a register variable with an asm label specified, then this // is a GNU extension. if (SC == VarDecl::Register && D.getAsmLabel()) @@ -1805,7 +2164,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (DC->isRecord() && !CurContext->isRecord()) { // This is an out-of-line definition of a static data member. if (SC == VarDecl::Static) { - Diag(D.getDeclSpec().getStorageClassSpecLoc(), + Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_out_of_line) << CodeModificationHint::CreateRemoval( SourceRange(D.getDeclSpec().getStorageClassSpecLoc())); @@ -1815,22 +2174,48 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (SC == VarDecl::Static) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) { if (RD->isLocalClass()) - Diag(D.getIdentifierLoc(), + Diag(D.getIdentifierLoc(), diag::err_static_data_member_not_allowed_in_local_class) << Name << RD->getDeclName(); } } - - - // The variable can not - NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), - II, R, SC, - // FIXME: Move to DeclGroup... - D.getDeclSpec().getSourceRange().getBegin()); + + // Match up the template parameter lists with the scope specifier, then + // determine whether we have a template or a template specialization. + bool isExplicitSpecialization = false; + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier( + D.getDeclSpec().getSourceRange().getBegin(), + D.getCXXScopeSpec(), + (TemplateParameterList**)TemplateParamLists.get(), + TemplateParamLists.size(), + isExplicitSpecialization)) { + if (TemplateParams->size() > 0) { + // There is no such thing as a variable template. + Diag(D.getIdentifierLoc(), diag::err_template_variable) + << II + << SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc()); + return 0; + } else { + // There is an extraneous 'template<>' for this variable. Complain + // about it, but allow the declaration of the variable. + Diag(TemplateParams->getTemplateLoc(), + diag::err_template_variable_noparams) + << II + << SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc()); + + isExplicitSpecialization = true; + } + } + + NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), + II, R, DInfo, SC); if (D.isInvalidType()) NewVD->setInvalidDecl(); - + if (D.getDeclSpec().isThreadSpecified()) { if (NewVD->hasLocalStorage()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global); @@ -1850,7 +2235,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Handle GNU asm-label extension (encoded as an attribute). if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. - StringLiteral *SE = cast<StringLiteral>(E); + StringLiteral *SE = cast<StringLiteral>(E); NewVD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(), SE->getByteLength()))); } @@ -1861,8 +2246,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (PrevDecl && !isDeclInScope(PrevDecl, DC, S) && !(NewVD->hasLinkage() && isOutOfScopePreviousDeclaration(PrevDecl, DC, Context))) - PrevDecl = 0; - + PrevDecl = 0; + // Merge the decl with the existing one if appropriate. if (PrevDecl) { if (isa<FieldDecl>(PrevDecl) && D.getCXXScopeSpec().isSet()) { @@ -1875,16 +2260,31 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } else if (D.getCXXScopeSpec().isSet()) { // No previous declaration in the qualifying scope. - Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member) - << Name << D.getCXXScopeSpec().getRange(); + Diag(D.getIdentifierLoc(), diag::err_no_member) + << Name << computeDeclContext(D.getCXXScopeSpec(), true) + << D.getCXXScopeSpec().getRange(); NewVD->setInvalidDecl(); } CheckVariableDeclaration(NewVD, PrevDecl, Redeclaration); + // This is an explicit specialization of a static data member. Check it. + if (isExplicitSpecialization && !NewVD->isInvalidDecl() && + CheckMemberSpecialization(NewVD, PrevDecl)) + NewVD->setInvalidDecl(); + + // attributes declared post-definition are currently ignored + if (PrevDecl) { + const VarDecl *Def = 0, *PrevVD = dyn_cast<VarDecl>(PrevDecl); + if (PrevVD->getDefinition(Def) && D.hasAttributes()) { + Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition); + Diag(Def->getLocation(), diag::note_previous_definition); + } + } + // If this is a locally-scoped extern C variable, update the map of // such variables. - if (CurContext->isFunctionOrMethod() && NewVD->isExternC(Context) && + if (CurContext->isFunctionOrMethod() && NewVD->isExternC() && !NewVD->isInvalidDecl()) RegisterLocallyScopedExternCDecl(NewVD, PrevDecl, S); @@ -1906,17 +2306,17 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, // If the decl is already known invalid, don't check it. if (NewVD->isInvalidDecl()) return; - + QualType T = NewVD->getType(); if (T->isObjCInterfaceType()) { Diag(NewVD->getLocation(), diag::err_statically_allocated_object); return NewVD->setInvalidDecl(); } - + // The variable can not have an abstract class type. if (RequireNonAbstractType(NewVD->getLocation(), T, - diag::err_abstract_type_in_decl, + diag::err_abstract_type_in_decl, AbstractVariableType)) return NewVD->setInvalidDecl(); @@ -1934,21 +2334,22 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); bool isVM = T->isVariablyModifiedType(); - if (isVM || NewVD->hasAttr<CleanupAttr>()) + if (isVM || NewVD->hasAttr<CleanupAttr>() || + NewVD->hasAttr<BlocksAttr>()) CurFunctionNeedsScopeChecking = true; - + if ((isVM && NewVD->hasLinkage()) || (T->isVariableArrayType() && NewVD->hasGlobalStorage())) { bool SizeIsNegative; QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative); - + if (FixedTy.isNull() && T->isVariableArrayType()) { const VariableArrayType *VAT = Context.getAsVariableArrayType(T); - // FIXME: This won't give the correct result for - // int a[10][n]; + // FIXME: This won't give the correct result for + // int a[10][n]; SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange(); - + if (NewVD->isFileVarDecl()) Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope) << SizeRange; @@ -1959,8 +2360,8 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage) << SizeRange; return NewVD->setInvalidDecl(); - } - + } + if (FixedTy.isNull()) { if (NewVD->isFileVarDecl()) Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope); @@ -1968,12 +2369,12 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage); return NewVD->setInvalidDecl(); } - + Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); NewVD->setType(FixedTy); } - if (!PrevDecl && NewVD->isExternC(Context)) { + if (!PrevDecl && NewVD->isExternC()) { // Since we did not find anything by this name and we're declaring // an extern "C" variable, look for a non-visible extern "C" // declaration with the same name. @@ -1993,7 +2394,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, Diag(NewVD->getLocation(), diag::err_block_on_nonlocal); return NewVD->setInvalidDecl(); } - + if (isVM && NewVD->hasAttr<BlocksAttr>()) { Diag(NewVD->getLocation(), diag::err_block_on_vm); return NewVD->setInvalidDecl(); @@ -2005,9 +2406,43 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, } } -NamedDecl* +static bool isUsingDecl(Decl *D) { + return isa<UsingDecl>(D) || isa<UnresolvedUsingDecl>(D); +} + +/// \brief Data used with FindOverriddenMethod +struct FindOverriddenMethodData { + Sema *S; + CXXMethodDecl *Method; +}; + +/// \brief Member lookup function that determines whether a given C++ +/// method overrides a method in a base class, to be used with +/// CXXRecordDecl::lookupInBases(). +static bool FindOverriddenMethod(CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *UserData) { + RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); + + FindOverriddenMethodData *Data + = reinterpret_cast<FindOverriddenMethodData*>(UserData); + for (Path.Decls = BaseRecord->lookup(Data->Method->getDeclName()); + Path.Decls.first != Path.Decls.second; + ++Path.Decls.first) { + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*Path.Decls.first)) { + OverloadedFunctionDecl::function_iterator MatchedDecl; + if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, MatchedDecl)) + return true; + } + } + + return false; +} + +NamedDecl* Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, NamedDecl* PrevDecl, + QualType R, DeclaratorInfo *DInfo, + NamedDecl* PrevDecl, MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition, bool &Redeclaration) { assert(R.getTypePtr()->isFunctionType()); @@ -2019,7 +2454,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, case DeclSpec::SCS_auto: case DeclSpec::SCS_register: case DeclSpec::SCS_mutable: - Diag(D.getDeclSpec().getStorageClassSpecLoc(), + Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_typecheck_sclass_func); D.setInvalidType(); break; @@ -2032,11 +2467,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // block scope shall have no explicit storage-class specifier // other than extern // See also (C++ [dcl.stc]p4). - Diag(D.getDeclSpec().getStorageClassSpecLoc(), + Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_block_func); SC = FunctionDecl::None; } else - SC = FunctionDecl::Static; + SC = FunctionDecl::Static; break; } case DeclSpec::SCS_private_extern: SC = FunctionDecl::PrivateExtern;break; @@ -2045,35 +2480,43 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + bool isFriend = D.getDeclSpec().isFriendSpecified(); bool isInline = D.getDeclSpec().isInlineSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); bool isExplicit = D.getDeclSpec().isExplicitSpecified(); // Check that the return type is not an abstract class type. // For record types, this is done by the AbstractClassUsageDiagnoser once - // the class has been completely parsed. + // the class has been completely parsed. if (!DC->isRecord() && - RequireNonAbstractType(D.getIdentifierLoc(), - R->getAsFunctionType()->getResultType(), - diag::err_abstract_type_in_decl, + RequireNonAbstractType(D.getIdentifierLoc(), + R->getAs<FunctionType>()->getResultType(), + diag::err_abstract_type_in_decl, AbstractReturnType)) D.setInvalidType(); - + // Do not allow returning a objc interface by-value. - if (R->getAsFunctionType()->getResultType()->isObjCInterfaceType()) { + if (R->getAs<FunctionType>()->getResultType()->isObjCInterfaceType()) { Diag(D.getIdentifierLoc(), diag::err_object_cannot_be_passed_returned_by_value) << 0 - << R->getAsFunctionType()->getResultType(); + << R->getAs<FunctionType>()->getResultType(); D.setInvalidType(); } - // Check that we can declare a template here. - if (TemplateParamLists.size() && - CheckTemplateDeclScope(S, TemplateParamLists)) - return 0; - bool isVirtualOkay = false; FunctionDecl *NewFD; + + if (isFriend) { + // DC is the namespace in which the function is being declared. + assert((DC->isFileContext() || PrevDecl) && "previously-undeclared " + "friend function being created in a non-namespace context"); + + // C++ [class.friend]p5 + // A function can be defined in a friend declaration of a + // class . . . . Such a function is implicitly inline. + isInline |= IsFunctionDefinition; + } + if (D.getKind() == Declarator::DK_Constructor) { // This is a C++ constructor declaration. assert(DC->isRecord() && @@ -2082,19 +2525,19 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, R = CheckConstructorDeclarator(D, R, SC); // Create the new declaration - NewFD = CXXConstructorDecl::Create(Context, + NewFD = CXXConstructorDecl::Create(Context, cast<CXXRecordDecl>(DC), - D.getIdentifierLoc(), Name, R, + D.getIdentifierLoc(), Name, R, DInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false); } else if (D.getKind() == Declarator::DK_Destructor) { // This is a C++ destructor declaration. if (DC->isRecord()) { R = CheckDestructorDeclarator(D, SC); - + NewFD = CXXDestructorDecl::Create(Context, cast<CXXRecordDecl>(DC), - D.getIdentifierLoc(), Name, R, + D.getIdentifierLoc(), Name, R, isInline, /*isImplicitlyDeclared=*/false); @@ -2105,10 +2548,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Create a FunctionDecl to satisfy the function definition parsing // code path. NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(), - Name, R, SC, isInline, - /*hasPrototype=*/true, - // FIXME: Move to DeclGroup... - D.getDeclSpec().getSourceRange().getBegin()); + Name, R, DInfo, SC, isInline, + /*hasPrototype=*/true); D.setInvalidType(); } } else if (D.getKind() == Declarator::DK_Conversion) { @@ -2117,29 +2558,29 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, diag::err_conv_function_not_member); return 0; } - + CheckConversionDeclarator(D, R, SC); NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC), - D.getIdentifierLoc(), Name, R, + D.getIdentifierLoc(), Name, R, DInfo, isInline, isExplicit); - + isVirtualOkay = true; } else if (DC->isRecord()) { // If the of the function is the same as the name of the record, then this - // must be an invalid constructor that has a return type. - // (The parser checks for a return type and makes the declarator a + // must be an invalid constructor that has a return type. + // (The parser checks for a return type and makes the declarator a // constructor if it has no return type). - // must have an invalid constructor that has a return type + // must have an invalid constructor that has a return type if (Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){ Diag(D.getIdentifierLoc(), diag::err_constructor_return_type) << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) << SourceRange(D.getIdentifierLoc()); return 0; } - + // This is a C++ method declaration. NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC), - D.getIdentifierLoc(), Name, R, + D.getIdentifierLoc(), Name, R, DInfo, (SC == FunctionDecl::Static), isInline); isVirtualOkay = (SC != FunctionDecl::Static); @@ -2150,44 +2591,56 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // - there is a prototype in the declarator, or // - the type R of the function is some kind of typedef or other reference // to a type name (which eventually refers to a function type). - bool HasPrototype = + bool HasPrototype = getLangOptions().CPlusPlus || (D.getNumTypeObjects() && D.getTypeObject(0).Fun.hasPrototype) || (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType()); - + NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(), - Name, R, SC, isInline, HasPrototype, - // FIXME: Move to DeclGroup... - D.getDeclSpec().getSourceRange().getBegin()); + Name, R, DInfo, SC, isInline, HasPrototype); } if (D.isInvalidType()) NewFD->setInvalidDecl(); - + // Set the lexical context. If the declarator has a C++ - // scope specifier, the lexical context will be different - // from the semantic context. + // scope specifier, or is the object of a friend declaration, the + // lexical context will be different from the semantic context. NewFD->setLexicalDeclContext(CurContext); - // If there is a template parameter list, then we are dealing with a - // template declaration or specialization. + // Match up the template parameter lists with the scope specifier, then + // determine whether we have a template or a template specialization. FunctionTemplateDecl *FunctionTemplate = 0; - if (TemplateParamLists.size()) { - // FIXME: member templates! - TemplateParameterList *TemplateParams - = static_cast<TemplateParameterList *>(*TemplateParamLists.release()); - + bool isExplicitSpecialization = false; + bool isFunctionTemplateSpecialization = false; + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier( + D.getDeclSpec().getSourceRange().getBegin(), + D.getCXXScopeSpec(), + (TemplateParameterList**)TemplateParamLists.get(), + TemplateParamLists.size(), + isExplicitSpecialization)) { if (TemplateParams->size() > 0) { // This is a function template - FunctionTemplate = FunctionTemplateDecl::Create(Context, CurContext, + + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + return 0; + + FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, NewFD->getLocation(), Name, TemplateParams, NewFD); + FunctionTemplate->setLexicalDeclContext(CurContext); NewFD->setDescribedFunctionTemplate(FunctionTemplate); } else { - // FIXME: Handle function template specializations + // This is a function template specialization. + isFunctionTemplateSpecialization = true; } + + // FIXME: Free this memory properly. + TemplateParamLists.release(); } // C++ [dcl.fct.spec]p5: @@ -2197,7 +2650,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // if (isVirtual && !NewFD->isInvalidDecl()) { if (!isVirtualOkay) { - Diag(D.getDeclSpec().getVirtualSpecLoc(), + Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_non_function); } else if (!CurContext->isRecord()) { // 'virtual' was specified outside of the class. @@ -2210,28 +2663,47 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, CXXRecordDecl *CurClass = cast<CXXRecordDecl>(DC); CurClass->setAggregate(false); CurClass->setPOD(false); + CurClass->setEmpty(false); CurClass->setPolymorphic(true); CurClass->setHasTrivialConstructor(false); + CurClass->setHasTrivialCopyConstructor(false); + CurClass->setHasTrivialCopyAssignment(false); + } + } + + if (isFriend) { + if (FunctionTemplate) { + FunctionTemplate->setObjectOfFriendDecl( + /* PreviouslyDeclared= */ PrevDecl != NULL); + FunctionTemplate->setAccess(AS_public); } + else + NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ PrevDecl != NULL); + + NewFD->setAccess(AS_public); } + if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) { // Look for virtual methods in base classes that this method might override. - - BasePaths Paths; - if (LookupInBases(cast<CXXRecordDecl>(DC), - MemberLookupCriteria(NewMD), Paths)) { - for (BasePaths::decl_iterator I = Paths.found_decls_begin(), + CXXBasePaths Paths; + FindOverriddenMethodData Data; + Data.Method = NewMD; + Data.S = this; + if (cast<CXXRecordDecl>(DC)->lookupInBases(&FindOverriddenMethod, &Data, + Paths)) { + for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(), E = Paths.found_decls_end(); I != E; ++I) { if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) { - if (!CheckOverridingFunctionReturnType(NewMD, OldMD)) + if (!CheckOverridingFunctionReturnType(NewMD, OldMD) && + !CheckOverridingFunctionExceptionSpec(NewMD, OldMD)) NewMD->addOverriddenMethod(OldMD); } } } } - - if (SC == FunctionDecl::Static && isa<CXXMethodDecl>(NewFD) && + + if (SC == FunctionDecl::Static && isa<CXXMethodDecl>(NewFD) && !CurContext->isRecord()) { // C++ [class.static]p1: // A data or function member of a class may be declared static @@ -2240,7 +2712,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Complain about the 'static' specifier if it's on an out-of-line // member function definition. - Diag(D.getDeclSpec().getStorageClassSpecLoc(), + Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_out_of_line) << CodeModificationHint::CreateRemoval( SourceRange(D.getDeclSpec().getStorageClassSpecLoc())); @@ -2249,7 +2721,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Handle GNU asm-label extension (encoded as an attribute). if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. - StringLiteral *SE = cast<StringLiteral>(E); + StringLiteral *SE = cast<StringLiteral>(E); NewFD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(), SE->getByteLength()))); } @@ -2278,11 +2750,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, Diag(Param->getLocation(), diag::err_param_typedef_of_void); // FIXME: Leaks decl? } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) { - for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) - Params.push_back(FTI.ArgInfo[i].Param.getAs<ParmVarDecl>()); + for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { + ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>(); + assert(Param->getDeclContext() != NewFD && "Was set before ?"); + Param->setDeclContext(NewFD); + Params.push_back(Param); + } } - - } else if (const FunctionProtoType *FT = R->getAsFunctionProtoType()) { + + } else if (const FunctionProtoType *FT = R->getAs<FunctionProtoType>()) { // When we're declaring a function with a typedef, typeof, etc as in the // following example, we'll need to synthesize (unnamed) // parameters for use in the declaration. @@ -2291,13 +2767,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // typedef void fn(int); // fn f; // @endcode - + // Synthesize a parameter for each argument type. for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(), AE = FT->arg_type_end(); AI != AE; ++AI) { ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, SourceLocation(), 0, - *AI, VarDecl::None, 0); + *AI, /*DInfo=*/0, + VarDecl::None, 0); Param->setImplicit(); Params.push_back(Param); } @@ -2307,7 +2784,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } // Finally, we know we have the right number of parameters, install them. NewFD->setParams(Context, Params.data(), Params.size()); - + // If name lookup finds a previous declaration that is not in the // same scope as the new declaration, this may still be an // acceptable redeclaration. @@ -2316,27 +2793,80 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isOutOfScopePreviousDeclaration(PrevDecl, DC, Context))) PrevDecl = 0; + // If the declarator is a template-id, translate the parser's template + // argument list into our AST format. + bool HasExplicitTemplateArgs = false; + llvm::SmallVector<TemplateArgument, 16> TemplateArgs; + SourceLocation LAngleLoc, RAngleLoc; + if (D.getKind() == Declarator::DK_TemplateId) { + TemplateIdAnnotation *TemplateId = D.getTemplateId(); + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->getTemplateArgIsType(), + TemplateId->NumArgs); + translateTemplateArguments(TemplateArgsPtr, + TemplateId->getTemplateArgLocations(), + TemplateArgs); + TemplateArgsPtr.release(); + + HasExplicitTemplateArgs = true; + LAngleLoc = TemplateId->LAngleLoc; + RAngleLoc = TemplateId->RAngleLoc; + + if (FunctionTemplate) { + // FIXME: Diagnose function template with explicit template + // arguments. + HasExplicitTemplateArgs = false; + } else if (!isFunctionTemplateSpecialization && + !D.getDeclSpec().isFriendSpecified()) { + // We have encountered something that the user meant to be a + // specialization (because it has explicitly-specified template + // arguments) but that was not introduced with a "template<>" (or had + // too few of them). + Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header) + << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc) + << CodeModificationHint::CreateInsertion( + D.getDeclSpec().getSourceRange().getBegin(), + "template<> "); + isFunctionTemplateSpecialization = true; + } + } + + if (isFunctionTemplateSpecialization) { + if (CheckFunctionTemplateSpecialization(NewFD, HasExplicitTemplateArgs, + LAngleLoc, TemplateArgs.data(), + TemplateArgs.size(), RAngleLoc, + PrevDecl)) + NewFD->setInvalidDecl(); + } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) && + CheckMemberSpecialization(NewFD, PrevDecl)) + NewFD->setInvalidDecl(); + // Perform semantic checking on the function declaration. bool OverloadableAttrRequired = false; // FIXME: HACK! - CheckFunctionDeclaration(NewFD, PrevDecl, Redeclaration, - /*FIXME:*/OverloadableAttrRequired); + CheckFunctionDeclaration(NewFD, PrevDecl, isExplicitSpecialization, + Redeclaration, /*FIXME:*/OverloadableAttrRequired); if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) { // An out-of-line member function declaration must also be a // definition (C++ [dcl.meaning]p1). - if (!IsFunctionDefinition) { + // Note that this is not the case for explicit specializations of + // function templates or member functions of class templates, per + // C++ [temp.expl.spec]p2. + if (!IsFunctionDefinition && !isFriend && + !isFunctionTemplateSpecialization && !isExplicitSpecialization) { Diag(NewFD->getLocation(), diag::err_out_of_line_declaration) << D.getCXXScopeSpec().getRange(); NewFD->setInvalidDecl(); - } else if (!Redeclaration && (!PrevDecl || !isa<UsingDecl>(PrevDecl))) { + } else if (!Redeclaration && (!PrevDecl || !isUsingDecl(PrevDecl))) { // The user tried to provide an out-of-line definition for a // function that is a member of a class or namespace, but there - // was no such member function declared (C++ [class.mfct]p2, + // was no such member function declared (C++ [class.mfct]p2, // C++ [namespace.memdef]p2). For example: - // + // // class X { // void f() const; - // }; + // }; // // void X::f() { } // ill-formed // @@ -2344,12 +2874,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // matches (e.g., those that differ only in cv-qualifiers and // whether the parameter types are references). Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match) - << cast<NamedDecl>(DC) << D.getCXXScopeSpec().getRange(); + << Name << DC << D.getCXXScopeSpec().getRange(); NewFD->setInvalidDecl(); - - LookupResult Prev = LookupQualifiedName(DC, Name, LookupOrdinaryName, - true); - assert(!Prev.isAmbiguous() && + + LookupResult Prev; + LookupQualifiedName(Prev, DC, Name, LookupOrdinaryName, true); + assert(!Prev.isAmbiguous() && "Cannot have an ambiguity in previous-declaration lookup"); for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end(); Func != FuncEnd; ++Func) { @@ -2357,7 +2887,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isNearlyMatchingFunction(Context, cast<FunctionDecl>(*Func), NewFD)) Diag((*Func)->getLocation(), diag::note_member_def_close_match); } - + PrevDecl = 0; } } @@ -2367,6 +2897,16 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // FIXME: This needs to happen before we merge declarations. Then, // let attribute merging cope with attribute conflicts. ProcessDeclAttributes(S, NewFD, D); + + // attributes declared post-definition are currently ignored + if (Redeclaration && PrevDecl) { + const FunctionDecl *Def, *PrevFD = dyn_cast<FunctionDecl>(PrevDecl); + if (PrevFD && PrevFD->getBody(Def) && D.hasAttributes()) { + Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition); + Diag(Def->getLocation(), diag::note_previous_definition); + } + } + AddKnownFunctionAttributes(NewFD); if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) { @@ -2375,14 +2915,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) << Redeclaration << NewFD; if (PrevDecl) - Diag(PrevDecl->getLocation(), + Diag(PrevDecl->getLocation(), diag::note_attribute_overloadable_prev_overload); NewFD->addAttr(::new (Context) OverloadableAttr()); } // If this is a locally-scoped extern C function, update the // map of such names. - if (CurContext->isFunctionOrMethod() && NewFD->isExternC(Context) + if (CurContext->isFunctionOrMethod() && NewFD->isExternC() && !NewFD->isInvalidDecl()) RegisterLocallyScopedExternCDecl(NewFD, PrevDecl, S); @@ -2391,10 +2931,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (FunctionTemplate && NewFD->isInvalidDecl()) FunctionTemplate->setInvalidDecl(); - + if (FunctionTemplate) return FunctionTemplate; - + return NewFD; } @@ -2408,8 +2948,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, /// that have been instantiated via C++ template instantiation (called /// via InstantiateDecl). /// +/// \param IsExplicitSpecialiation whether this new function declaration is +/// an explicit specialization of the previous declaration. +/// /// This sets NewFD->isInvalidDecl() to true if there was an error. void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, + bool IsExplicitSpecialization, bool &Redeclaration, bool &OverloadableAttrRequired) { // If NewFD is already known erroneous, don't do any of this checking. @@ -2423,51 +2967,11 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, return NewFD->setInvalidDecl(); } - // Semantic checking for this function declaration (in isolation). - if (getLangOptions().CPlusPlus) { - // C++-specific checks. - if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) { - CheckConstructor(Constructor); - } else if (isa<CXXDestructorDecl>(NewFD)) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent()); - Record->setUserDeclaredDestructor(true); - // C++ [class]p4: A POD-struct is an aggregate class that has [...] no - // user-defined destructor. - Record->setPOD(false); - - // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly- - // declared destructor. - Record->setHasTrivialDestructor(false); - } else if (CXXConversionDecl *Conversion - = dyn_cast<CXXConversionDecl>(NewFD)) - ActOnConversionDeclarator(Conversion); - - // Extra checking for C++ overloaded operators (C++ [over.oper]). - if (NewFD->isOverloadedOperator() && - CheckOverloadedOperatorDeclaration(NewFD)) - return NewFD->setInvalidDecl(); - } - - // C99 6.7.4p6: - // [... ] For a function with external linkage, the following - // restrictions apply: [...] If all of the file scope declarations - // for a function in a translation unit include the inline - // function specifier without extern, then the definition in that - // translation unit is an inline definition. An inline definition - // does not provide an external definition for the function, and - // does not forbid an external definition in another translation - // unit. - // - // Here we determine whether this function, in isolation, would be a - // C99 inline definition. MergeCompatibleFunctionDecls looks at - // previous declarations. - if (NewFD->isInline() && getLangOptions().C99 && - NewFD->getStorageClass() == FunctionDecl::None && - NewFD->getDeclContext()->getLookupContext()->isTranslationUnit()) - NewFD->setC99InlineDefinition(true); + if (NewFD->isMain()) + CheckMain(NewFD); // Check for a previous declaration of this name. - if (!PrevDecl && NewFD->isExternC(Context)) { + if (!PrevDecl && NewFD->isExternC()) { // Since we did not find anything by this name and we're declaring // an extern "C" function, look for a non-visible extern "C" // declaration with the same name. @@ -2492,24 +2996,23 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, // Functions marked "overloadable" must have a prototype (that // we can't get through declaration merging). - if (!NewFD->getType()->getAsFunctionProtoType()) { + if (!NewFD->getType()->getAs<FunctionProtoType>()) { Diag(NewFD->getLocation(), diag::err_attribute_overloadable_no_prototype) << NewFD; Redeclaration = true; // Turn this into a variadic function with no parameters. QualType R = Context.getFunctionType( - NewFD->getType()->getAsFunctionType()->getResultType(), + NewFD->getType()->getAs<FunctionType>()->getResultType(), 0, 0, true, 0); NewFD->setType(R); return NewFD->setInvalidDecl(); } } - if (PrevDecl && - (!AllowOverloadingOfFunction(PrevDecl, Context) || - !IsOverload(NewFD, PrevDecl, MatchedDecl)) && - !isa<UsingDecl>(PrevDecl)) { + if (PrevDecl && + (!AllowOverloadingOfFunction(PrevDecl, Context) || + !IsOverload(NewFD, PrevDecl, MatchedDecl)) && !isUsingDecl(PrevDecl)) { Redeclaration = true; Decl *OldDecl = PrevDecl; @@ -2519,23 +3022,160 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, OldDecl = *MatchedDecl; // NewFD and OldDecl represent declarations that need to be - // merged. + // merged. if (MergeFunctionDecl(NewFD, OldDecl)) return NewFD->setInvalidDecl(); if (FunctionTemplateDecl *OldTemplateDecl - = dyn_cast<FunctionTemplateDecl>(OldDecl)) - NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); - else + = dyn_cast<FunctionTemplateDecl>(OldDecl)) { + NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); + FunctionTemplateDecl *NewTemplateDecl + = NewFD->getDescribedFunctionTemplate(); + assert(NewTemplateDecl && "Template/non-template mismatch"); + if (CXXMethodDecl *Method + = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) { + Method->setAccess(OldTemplateDecl->getAccess()); + NewTemplateDecl->setAccess(OldTemplateDecl->getAccess()); + } + + // If this is an explicit specialization of a member that is a function + // template, mark it as a member specialization. + if (IsExplicitSpecialization && + NewTemplateDecl->getInstantiatedFromMemberTemplate()) { + NewTemplateDecl->setMemberSpecialization(); + assert(OldTemplateDecl->isMemberSpecialization()); + } + } else { + if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions + NewFD->setAccess(OldDecl->getAccess()); NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl)); + } } } - // In C++, check default arguments now that we have merged decls. Unless - // the lexical context is the class, because in this case this is done - // during delayed parsing anyway. - if (getLangOptions().CPlusPlus && !CurContext->isRecord()) - CheckCXXDefaultArguments(NewFD); + // Semantic checking for this function declaration (in isolation). + if (getLangOptions().CPlusPlus) { + // C++-specific checks. + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) { + CheckConstructor(Constructor); + } else if (isa<CXXDestructorDecl>(NewFD)) { + CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent()); + QualType ClassType = Context.getTypeDeclType(Record); + if (!ClassType->isDependentType()) { + DeclarationName Name + = Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalType(ClassType)); + if (NewFD->getDeclName() != Name) { + Diag(NewFD->getLocation(), diag::err_destructor_name); + return NewFD->setInvalidDecl(); + } + } + Record->setUserDeclaredDestructor(true); + // C++ [class]p4: A POD-struct is an aggregate class that has [...] no + // user-defined destructor. + Record->setPOD(false); + + // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly- + // declared destructor. + // FIXME: C++0x: don't do this for "= default" destructors + Record->setHasTrivialDestructor(false); + } else if (CXXConversionDecl *Conversion + = dyn_cast<CXXConversionDecl>(NewFD)) + ActOnConversionDeclarator(Conversion); + + // Extra checking for C++ overloaded operators (C++ [over.oper]). + if (NewFD->isOverloadedOperator() && + CheckOverloadedOperatorDeclaration(NewFD)) + return NewFD->setInvalidDecl(); + + // In C++, check default arguments now that we have merged decls. Unless + // the lexical context is the class, because in this case this is done + // during delayed parsing anyway. + if (!CurContext->isRecord()) + CheckCXXDefaultArguments(NewFD); + } +} + +void Sema::CheckMain(FunctionDecl* FD) { + // C++ [basic.start.main]p3: A program that declares main to be inline + // or static is ill-formed. + // C99 6.7.4p4: In a hosted environment, the inline function specifier + // shall not appear in a declaration of main. + // static main is not an error under C99, but we should warn about it. + bool isInline = FD->isInline(); + bool isStatic = FD->getStorageClass() == FunctionDecl::Static; + if (isInline || isStatic) { + unsigned diagID = diag::warn_unusual_main_decl; + if (isInline || getLangOptions().CPlusPlus) + diagID = diag::err_unusual_main_decl; + + int which = isStatic + (isInline << 1) - 1; + Diag(FD->getLocation(), diagID) << which; + } + + QualType T = FD->getType(); + assert(T->isFunctionType() && "function decl is not of function type"); + const FunctionType* FT = T->getAs<FunctionType>(); + + if (!Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) { + // TODO: add a replacement fixit to turn the return type into 'int'. + Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint); + FD->setInvalidDecl(true); + } + + // Treat protoless main() as nullary. + if (isa<FunctionNoProtoType>(FT)) return; + + const FunctionProtoType* FTP = cast<const FunctionProtoType>(FT); + unsigned nparams = FTP->getNumArgs(); + assert(FD->getNumParams() == nparams); + + if (nparams > 3) { + Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams; + FD->setInvalidDecl(true); + nparams = 3; + } + + // FIXME: a lot of the following diagnostics would be improved + // if we had some location information about types. + + QualType CharPP = + Context.getPointerType(Context.getPointerType(Context.CharTy)); + QualType Expected[] = { Context.IntTy, CharPP, CharPP }; + + for (unsigned i = 0; i < nparams; ++i) { + QualType AT = FTP->getArgType(i); + + bool mismatch = true; + + if (Context.hasSameUnqualifiedType(AT, Expected[i])) + mismatch = false; + else if (Expected[i] == CharPP) { + // As an extension, the following forms are okay: + // char const ** + // char const * const * + // char * const * + + QualifierCollector qs; + const PointerType* PT; + if ((PT = qs.strip(AT)->getAs<PointerType>()) && + (PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) && + (QualType(qs.strip(PT->getPointeeType()), 0) == Context.CharTy)) { + qs.removeConst(); + mismatch = !qs.empty(); + } + } + + if (mismatch) { + Diag(FD->getLocation(), diag::err_main_arg_wrong) << i << Expected[i]; + // TODO: suggest replacing given type with expected type + FD->setInvalidDecl(true); + } + } + + if (nparams == 1 && !FD->isInvalidDecl()) { + Diag(FD->getLocation(), diag::warn_main_one_arg); + } } bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { @@ -2554,8 +3194,8 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { return true; } -void Sema::AddInitializerToDecl(DeclPtrTy dcl, FullExprArg init) { - AddInitializerToDecl(dcl, init.release(), /*DirectInit=*/false); +void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init) { + AddInitializerToDecl(dcl, move(init), /*DirectInit=*/false); } /// AddInitializerToDecl - Adds the initializer Init to the @@ -2567,7 +3207,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { // the initializer. if (RealDecl == 0) return; - + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) { // With declarators parsed the way they are, the parser cannot // distinguish between a normal initializer and a pure-specifier. @@ -2616,7 +3256,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { const VarDecl *Def = 0; if (VDecl->getDefinition(Def)) { - Diag(VDecl->getLocation(), diag::err_redefinition) + Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); Diag(Def->getLocation(), diag::note_previous_definition); VDecl->setInvalidDecl(); @@ -2639,7 +3279,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(), VDecl->getDeclName(), DirectInit)) VDecl->setInvalidDecl(); - + // C++ 3.6.2p2, allow dynamic initialization of static initializers. // Don't check invalid declarations to avoid emitting useless diagnostics. if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) { @@ -2647,7 +3287,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { CheckForConstantInitializer(Init, DclT); } } - } else if (VDecl->isStaticDataMember() && + } else if (VDecl->isStaticDataMember() && VDecl->getLexicalDeclContext()->isRecord()) { // This is an in-class initialization for a static data member, e.g., // @@ -2663,7 +3303,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { // if it declares a static member (9.4) of const integral or // const enumeration type, see 9.4.2. QualType T = VDecl->getType(); - if (!T->isDependentType() && + if (!T->isDependentType() && (!Context.getCanonicalType(T).isConstQualified() || !T->isIntegralType())) { Diag(VDecl->getLocation(), diag::err_member_initialization) @@ -2678,7 +3318,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { if (!Init->isTypeDependent() && !Init->getType()->isIntegralType()) { // We have a non-dependent, non-integral or enumeration type. - Diag(Init->getSourceRange().getBegin(), + Diag(Init->getSourceRange().getBegin(), diag::err_in_class_initializer_non_integral_type) << Init->getType() << Init->getSourceRange(); VDecl->setInvalidDecl(); @@ -2701,7 +3341,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(), VDecl->getDeclName(), DirectInit)) VDecl->setInvalidDecl(); - + // C++ 3.6.2p2, allow dynamic initialization of static initializers. // Don't check invalid declarations to avoid emitting useless diagnostics. if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) { @@ -2710,14 +3350,16 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { } } // If the type changed, it means we had an incomplete type that was - // completed by the initializer. For example: + // 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); } - + + Init = MaybeCreateCXXExprWithTemporaries(Init, + /*ShouldDestroyTemporaries=*/true); // Attach the initializer to the decl. VDecl->setInit(Context, Init); @@ -2725,17 +3367,15 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { // remove it from the set of tentative definitions. if (VDecl->getPreviousDeclaration() && VDecl->getPreviousDeclaration()->isTentativeDefinition(Context)) { - llvm::DenseMap<DeclarationName, VarDecl *>::iterator Pos - = TentativeDefinitions.find(VDecl->getDeclName()); - assert(Pos != TentativeDefinitions.end() && - "Unrecorded tentative definition?"); - TentativeDefinitions.erase(Pos); + bool Deleted = TentativeDefinitions.erase(VDecl->getDeclName()); + assert(Deleted && "Unrecorded tentative definition?"); Deleted=Deleted; } return; } -void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) { +void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, + bool TypeContainsUndeducedAuto) { Decl *RealDecl = dcl.getAs<Decl>(); // If there is no declaration, there was an error parsing it. Just ignore it. @@ -2746,8 +3386,20 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) { QualType Type = Var->getType(); // Record tentative definitions. - if (Var->isTentativeDefinition(Context)) - TentativeDefinitions[Var->getDeclName()] = Var; + if (Var->isTentativeDefinition(Context)) { + std::pair<llvm::DenseMap<DeclarationName, VarDecl *>::iterator, bool> + InsertPair = + TentativeDefinitions.insert(std::make_pair(Var->getDeclName(), Var)); + + // Keep the latest definition in the map. If we see 'int i; int i;' we + // want the second one in the map. + InsertPair.first->second = Var; + + // However, for the list, we don't care about the order, just make sure + // that there are no dupes for a given declaration name. + if (InsertPair.second) + TentativeDefinitionList.push_back(Var->getDeclName()); + } // C++ [dcl.init.ref]p3: // The initializer can be omitted for a reference only in a @@ -2763,46 +3415,72 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) { return; } + // C++0x [dcl.spec.auto]p3 + if (TypeContainsUndeducedAuto) { + Diag(Var->getLocation(), diag::err_auto_var_requires_init) + << Var->getDeclName() << Type; + Var->setInvalidDecl(); + return; + } + + // C++ [temp.expl.spec]p15: + // An explicit specialization of a static data member of a template is a + // definition if the declaration includes an initializer; otherwise, it + // is a declaration. + if (Var->isStaticDataMember() && + Var->getInstantiatedFromStaticDataMember() && + Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return; + // C++ [dcl.init]p9: - // // If no initializer is specified for an object, and the object // is of (possibly cv-qualified) non-POD class type (or array // thereof), the object shall be default-initialized; if the // object is of const-qualified type, the underlying class type // shall have a user-declared default constructor. + // + // FIXME: Diagnose the "user-declared default constructor" bit. if (getLangOptions().CPlusPlus) { QualType InitType = Type; if (const ArrayType *Array = Context.getAsArrayType(Type)) InitType = Array->getElementType(); - if ((!Var->hasExternalStorage() && !Var->isExternC(Context)) && + if ((!Var->hasExternalStorage() && !Var->isExternC()) && InitType->isRecordType() && !InitType->isDependentType()) { - CXXRecordDecl *RD = - cast<CXXRecordDecl>(InitType->getAsRecordType()->getDecl()); - CXXConstructorDecl *Constructor = 0; - if (!RequireCompleteType(Var->getLocation(), InitType, - diag::err_invalid_incomplete_type_use)) - Constructor - = PerformInitializationByConstructor(InitType, 0, 0, + if (!RequireCompleteType(Var->getLocation(), InitType, + diag::err_invalid_incomplete_type_use)) { + ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); + + CXXConstructorDecl *Constructor + = PerformInitializationByConstructor(InitType, + MultiExprArg(*this, 0, 0), Var->getLocation(), SourceRange(Var->getLocation(), Var->getLocation()), Var->getDeclName(), - IK_Default); - if (!Constructor) + IK_Default, + ConstructorArgs); + + // FIXME: Location info for the variable initialization? + if (!Constructor) + Var->setInvalidDecl(); + else { + // FIXME: Cope with initialization of arrays + if (!Constructor->isTrivial() && + InitializeVarWithConstructor(Var, Constructor, InitType, + move_arg(ConstructorArgs))) + Var->setInvalidDecl(); + + FinalizeVarWithDestructor(Var, InitType); + } + } else { Var->setInvalidDecl(); - else { - if (!RD->hasTrivialConstructor()) - InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0); - // FIXME. Must do all that is needed to destroy the object - // on scope exit. For now, just mark the destructor as used. - MarkDestructorReferenced(Var->getLocation(), InitType); } } } #if 0 // FIXME: Temporarily disabled because we are not properly parsing - // linkage specifications on declarations, e.g., + // linkage specifications on declarations, e.g., // // extern "C" const CGPoint CGPointerZero; // @@ -2844,7 +3522,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, for (unsigned i = 0; i != NumDecls; ++i) if (Decl *D = Group[i].getAs<Decl>()) Decls.push_back(D); - + // Perform semantic analysis that depends on having fully processed both // the declarator and initializer. for (unsigned i = 0, e = Decls.size(); i != e; ++i) { @@ -2852,38 +3530,40 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (!IDecl) continue; QualType T = IDecl->getType(); - + // 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 (IDecl->isBlockVarDecl() && !IDecl->hasExternalStorage()) { if (!IDecl->isInvalidDecl() && - RequireCompleteType(IDecl->getLocation(), T, + RequireCompleteType(IDecl->getLocation(), T, diag::err_typecheck_decl_incomplete_type)) IDecl->setInvalidDecl(); } - // File scope. C99 6.9.2p2: A declaration of an identifier for and + // File scope. C99 6.9.2p2: A declaration of an identifier for an // 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 (IDecl->isTentativeDefinition(Context)) { - QualType CheckType = T; - unsigned DiagID = diag::err_typecheck_decl_incomplete_type; - - const IncompleteArrayType *ArrayT = Context.getAsIncompleteArrayType(T); - if (ArrayT) { - CheckType = ArrayT->getElementType(); - DiagID = diag::err_illegal_decl_array_incomplete_type; - } - - if (IDecl->isInvalidDecl()) { - // Do nothing with invalid declarations - } else if ((ArrayT || IDecl->getStorageClass() == VarDecl::Static) && - RequireCompleteType(IDecl->getLocation(), CheckType, DiagID)) { + if (IDecl->isTentativeDefinition(Context) && !IDecl->isInvalidDecl()) { + if (const IncompleteArrayType *ArrayT + = Context.getAsIncompleteArrayType(T)) { + if (RequireCompleteType(IDecl->getLocation(), + ArrayT->getElementType(), + diag::err_illegal_decl_array_incomplete_type)) + IDecl->setInvalidDecl(); + } else if (IDecl->getStorageClass() == VarDecl::Static) { // 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 + // a tentative definition and has internal linkage (C99 6.2.2p3), the // declared type shall not be an incomplete type. - IDecl->setInvalidDecl(); + // NOTE: code such as the following + // static struct s; + // struct s { int a; }; + // is accepted by gcc. Hence here we issue a warning instead of + // an error and we do not invalidate the static declaration. + // NOTE: to avoid multiple warnings, only check the first declaration. + if (IDecl->getPreviousDeclaration() == 0) + RequireCompleteType(IDecl->getLocation(), T, + diag::ext_typecheck_decl_incomplete_type); } } } @@ -2894,7 +3574,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() /// to introduce parameters into function prototype scope. -Sema::DeclPtrTy +Sema::DeclPtrTy Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); @@ -2917,10 +3597,12 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // parameter (C++ only). if (getLangOptions().CPlusPlus) CheckExtraCXXDefaultArguments(D); - + + DeclaratorInfo *DInfo = 0; TagDecl *OwnedDecl = 0; - QualType parmDeclType = GetTypeForDeclarator(D, S, /*Skip=*/0, &OwnedDecl); - + QualType parmDeclType = GetTypeForDeclarator(D, S, &DInfo, /*Skip=*/0, + &OwnedDecl); + if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) { // C++ [dcl.fct]p6: // Types shall not be defined in return or parameter types. @@ -2933,7 +3615,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // among each other. Here they can only shadow globals, which is ok. IdentifierInfo *II = D.getIdentifier(); if (II) { - if (NamedDecl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) { + if (NamedDecl *PrevDecl = LookupSingleName(S, II, LookupOrdinaryName)) { if (PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); @@ -2951,26 +3633,26 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // Parameters can not be abstract class types. // For record types, this is done by the AbstractClassUsageDiagnoser once - // the class has been completely parsed. - if (!CurContext->isRecord() && - RequireNonAbstractType(D.getIdentifierLoc(), parmDeclType, + // the class has been completely parsed. + if (!CurContext->isRecord() && + RequireNonAbstractType(D.getIdentifierLoc(), parmDeclType, diag::err_abstract_type_in_decl, AbstractParamType)) D.setInvalidType(true); QualType T = adjustParameterType(parmDeclType); - + ParmVarDecl *New; if (T == parmDeclType) // parameter type did not need adjustment - New = ParmVarDecl::Create(Context, CurContext, + New = ParmVarDecl::Create(Context, CurContext, D.getIdentifierLoc(), II, - parmDeclType, StorageClass, + parmDeclType, DInfo, StorageClass, 0); else // keep track of both the adjusted and unadjusted types - New = OriginalParmVarDecl::Create(Context, CurContext, - D.getIdentifierLoc(), II, T, + New = OriginalParmVarDecl::Create(Context, CurContext, + D.getIdentifierLoc(), II, T, DInfo, parmDeclType, StorageClass, 0); - + if (D.isInvalidType()) New->setInvalidDecl(); @@ -2981,14 +3663,25 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { diag::err_object_cannot_be_passed_returned_by_value) << 1 << T; New->setInvalidDecl(); } - + // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). if (D.getCXXScopeSpec().isSet()) { Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator) << D.getCXXScopeSpec().getRange(); New->setInvalidDecl(); } - + + // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage + // duration shall not be qualified by an address-space qualifier." + // Since all parameters have automatic store duration, they can not have + // an address space. + if (T.getAddressSpace() != 0) { + Diag(D.getIdentifierLoc(), + diag::err_arg_with_address_space); + New->setInvalidDecl(); + } + + // Add the parameter declaration into this scope. S->AddDecl(DeclPtrTy::make(New)); if (II) @@ -3025,14 +3718,15 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, // type. DeclSpec DS; const char* PrevSpec; // unused - DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc, - PrevSpec); + unsigned DiagID; // unused + DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc, + PrevSpec, DiagID); Declarator ParamD(DS, Declarator::KNRTypeListContext); ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc); FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD); } } - } + } } Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, @@ -3043,12 +3737,12 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; if (FTI.hasPrototype) { - // FIXME: Diagnose arguments without names in C. + // FIXME: Diagnose arguments without names in C. } - + Scope *ParentScope = FnBodyScope->getParent(); - DeclPtrTy DP = HandleDeclarator(ParentScope, D, + DeclPtrTy DP = HandleDeclarator(ParentScope, D, MultiTemplateParamsArg(*this), /*IsFunctionDefinition=*/true); return ActOnStartOfFunctionDef(FnBodyScope, DP); @@ -3057,10 +3751,16 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { if (!D) return D; - FunctionDecl *FD = cast<FunctionDecl>(D.getAs<Decl>()); + FunctionDecl *FD = 0; + + if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>(D.getAs<Decl>())) + FD = FunTmpl->getTemplatedDecl(); + else + FD = cast<FunctionDecl>(D.getAs<Decl>()); CurFunctionNeedsScopeChecking = false; - + // See if this is a redefinition. const FunctionDecl *Definition; if (FD->getBody(Definition)) { @@ -3069,7 +3769,7 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { } // Builtin functions cannot be defined. - if (unsigned BuiltinID = FD->getBuiltinID(Context)) { + if (unsigned BuiltinID = FD->getBuiltinID()) { if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { Diag(FD->getLocation(), diag::err_builtin_definition) << FD; FD->setInvalidDecl(); @@ -3126,7 +3826,7 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { // Checking attributes of current function definition // dllimport attribute. - if (FD->getAttr<DLLImportAttr>() && + if (FD->getAttr<DLLImportAttr>() && (!FD->getAttr<DLLExportAttr>())) { // dllimport attribute cannot be applied to definition. if (!(FD->getAttr<DLLImportAttr>())->isInherited()) { @@ -3155,23 +3855,39 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, bool IsInstantiation) { Decl *dcl = D.getAs<Decl>(); Stmt *Body = BodyArg.takeAs<Stmt>(); - if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) { + + FunctionDecl *FD = 0; + FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl); + if (FunTmpl) + FD = FunTmpl->getTemplatedDecl(); + else + FD = dyn_cast_or_null<FunctionDecl>(dcl); + + if (FD) { FD->setBody(Body); - + if (FD->isMain()) + // C and C++ allow for main to automagically return 0. + // Implements C++ [basic.start.main]p5 and C99 5.1.2.2.3. + FD->setHasImplicitReturnZero(true); + else + CheckFallThroughForFunctionDef(FD, Body); + if (!FD->isInvalidDecl()) DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); - + // C++ [basic.def.odr]p2: // [...] A virtual member function is used if it is not pure. [...] if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) if (Method->isVirtual() && !Method->isPure()) MarkDeclarationReferenced(Method->getLocation(), Method); - + assert(FD == getCurFunctionDecl() && "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) { assert(MD == getCurMethodDecl() && "Method parsing confused"); MD->setBody(Body); - + CheckFallThroughForFunctionDef(MD, Body); + MD->setEndLoc(Body->getLocEnd()); + if (!MD->isInvalidDecl()) DiagnoseUnusedParameters(MD->param_begin(), MD->param_end()); } else { @@ -3184,21 +3900,21 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, // Verify and clean out per-function state. assert(&getLabelMap() == &FunctionLabelMap && "Didn't pop block right?"); - + // Check goto/label use. for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator I = FunctionLabelMap.begin(), E = FunctionLabelMap.end(); I != E; ++I) { LabelStmt *L = I->second; - + // 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 (L->getSubStmt() != 0) continue; - + // 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. @@ -3207,7 +3923,7 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, L->Destroy(Context); continue; } - + // Otherwise, the body is valid: we want to stitch the label decl into the // function somewhere so that it is properly owned and so that the goto // has a valid target. Do this by creating a new compound stmt with the @@ -3231,17 +3947,20 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, if (CurFunctionNeedsScopeChecking) DiagnoseInvalidJumps(Body); - // C++ constructors that have function-try-blocks can't have return statements - // in the handlers of that block. (C++ [except.handle]p14) Verify this. - if (isa<CXXConstructorDecl>(dcl) && isa<CXXTryStmt>(Body)) + // C++ constructors that have function-try-blocks can't have return + // statements in the handlers of that block. (C++ [except.handle]p14) + // Verify this. + if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body)) DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body)); + if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) + computeBaseOrMembersToDestroy(Destructor); 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). -NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, +NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, Scope *S) { // Before we produce a declaration for an implicitly defined // function, see whether there was a locally-scoped declaration of @@ -3256,25 +3975,26 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, } // Extension in C99. Legal in C90, but warn about it. - if (getLangOptions().C99) + static const unsigned int BuiltinLen = strlen("__builtin_"); + if (II.getLength() > BuiltinLen && + std::equal(II.getName(), II.getName() + BuiltinLen, "__builtin_")) + Diag(Loc, diag::warn_builtin_unknown) << &II; + else if (getLangOptions().C99) Diag(Loc, diag::ext_implicit_function_decl) << &II; else Diag(Loc, diag::warn_implicit_function_decl) << &II; - - // 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); + unsigned DiagID; + bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID); Error = Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); Declarator D(DS, Declarator::BlockContext); D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0, 0, 0, false, SourceLocation(), - false, 0,0,0, Loc, D), + false, 0,0,0, Loc, Loc, D), SourceLocation()); D.SetIdentifier(&II, Loc); @@ -3282,8 +4002,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, DeclContext *PrevDC = CurContext; CurContext = Context.getTranslationUnitDecl(); - - FunctionDecl *FD = + + FunctionDecl *FD = dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>()); FD->setImplicit(); @@ -3306,7 +4026,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // If this is a built-in function, map its builtin attributes to // actual attributes. - if (unsigned BuiltinID = FD->getBuiltinID(Context)) { + if (unsigned BuiltinID = FD->getBuiltinID()) { // Handle printf-formatting attributes. unsigned FormatIdx; bool HasVAListArg; @@ -3324,15 +4044,18 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { if (!FD->getAttr<ConstAttr>()) FD->addAttr(::new (Context) ConstAttr()); } + + if (Context.BuiltinInfo.isNoReturn(BuiltinID)) + FD->addAttr(::new (Context) NoReturnAttr()); } IdentifierInfo *Name = FD->getIdentifier(); if (!Name) return; - if ((!getLangOptions().CPlusPlus && + if ((!getLangOptions().CPlusPlus && FD->getDeclContext()->isTranslationUnit()) || (isa<LinkageSpecDecl>(FD->getDeclContext()) && - cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() == + cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() == LinkageSpecDecl::lang_c)) { // Okay: this could be a libc/libm/Objective-C function we know // about. @@ -3340,13 +4063,16 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { return; if (Name->isStr("NSLog") || Name->isStr("NSLogv")) { + // FIXME: NSLog and NSLogv should be target specific if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) { // FIXME: We known better than our headers. const_cast<FormatAttr *>(Format)->setType("printf"); - } else + } else FD->addAttr(::new (Context) FormatAttr("printf", 1, Name->isStr("NSLogv") ? 0 : 2)); } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) { + // FIXME: asprintf and vasprintf aren't C99 functions. Should they be + // target-specific builtins, perhaps? if (!FD->getAttr<FormatAttr>()) FD->addAttr(::new (Context) FormatAttr("printf", 2, Name->isStr("vasprintf") ? 0 : 3)); @@ -3356,16 +4082,16 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) { 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, CurContext, D.getIdentifierLoc(), - D.getIdentifier(), + D.getIdentifier(), T); - - if (TagType *TT = dyn_cast<TagType>(T)) { + + if (const TagType *TT = T->getAs<TagType>()) { TagDecl *TD = TT->getDecl(); - + // If the TagDecl that the TypedefDecl points to is an anonymous decl // keep track of the TypedefDecl. if (!TD->getIdentifier() && !TD->getTypedefForAnonDecl()) @@ -3382,7 +4108,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) { /// as a redeclaration of the given tag declaration. /// /// \returns true if the new tag kind is acceptable, false otherwise. -bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, +bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, TagDecl::TagKind NewTag, SourceLocation NewTagLoc, const IdentifierInfo &Name) { @@ -3402,7 +4128,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, TagDecl::TagKind OldTag = Previous->getTagKind(); if (OldTag == NewTag) return true; - + if ((OldTag == TagDecl::TK_struct || OldTag == TagDecl::TK_class) && (NewTag == TagDecl::TK_struct || NewTag == TagDecl::TK_class)) { // Warn about the struct/class tag mismatch. @@ -3423,33 +4149,58 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, /// 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. -/// TagSpec indicates what kind of tag this is. TK indicates whether this is a +/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a /// reference/declaration/definition of a tag. -Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, +Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, const CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, AccessSpecifier AS, - bool &OwnedDecl) { + MultiTemplateParamsArg TemplateParameterLists, + bool &OwnedDecl, bool &IsDependent) { // If this is not a definition, it must have a name. - assert((Name != 0 || TK == TK_Definition) && + assert((Name != 0 || TUK == TUK_Definition) && "Nameless record must be a definition!"); OwnedDecl = false; - TagDecl::TagKind Kind; - switch (TagSpec) { - default: assert(0 && "Unknown tag type!"); - case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break; - case DeclSpec::TST_union: Kind = TagDecl::TK_union; break; - case DeclSpec::TST_class: Kind = TagDecl::TK_class; break; - case DeclSpec::TST_enum: Kind = TagDecl::TK_enum; break; + TagDecl::TagKind Kind = TagDecl::getTagKindForTypeSpec(TagSpec); + + // FIXME: Check explicit specializations more carefully. + bool isExplicitSpecialization = false; + if (TUK != TUK_Reference) { + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier(KWLoc, SS, + (TemplateParameterList**)TemplateParameterLists.get(), + TemplateParameterLists.size(), + isExplicitSpecialization)) { + if (TemplateParams->size() > 0) { + // This is a declaration or definition of a class template (which may + // be a member of another template). + OwnedDecl = false; + DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, + SS, Name, NameLoc, Attr, + TemplateParams, + AS); + TemplateParameterLists.release(); + return Result.get(); + } else { + // The "template<>" header is extraneous. + Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) + << ElaboratedType::getNameForTagKind(Kind) << Name; + isExplicitSpecialization = true; + } + } + + TemplateParameterLists.release(); } - + DeclContext *SearchDC = CurContext; DeclContext *DC = CurContext; NamedDecl *PrevDecl = 0; - + bool isStdBadAlloc = false; bool Invalid = false; + bool RedeclarationOnly = (TUK != TUK_Reference); + if (Name && SS.isNotEmpty()) { // We have a nested-name tag ('struct foo::bar'). @@ -3459,18 +4210,35 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, goto CreateNewDecl; } + // If this is a friend or a reference to a class in a dependent + // context, don't try to make a decl for it. + if (TUK == TUK_Friend || TUK == TUK_Reference) { + DC = computeDeclContext(SS, false); + if (!DC) { + IsDependent = true; + return DeclPtrTy(); + } + } + if (RequireCompleteDeclContext(SS)) return DeclPtrTy::make((Decl *)0); - DC = computeDeclContext(SS); + DC = computeDeclContext(SS, true); SearchDC = DC; // Look-up name inside 'foo::'. - PrevDecl - = dyn_cast_or_null<TagDecl>( - LookupQualifiedName(DC, Name, LookupTagName, true).getAsDecl()); + LookupResult R; + LookupQualifiedName(R, DC, Name, LookupTagName, RedeclarationOnly); + + if (R.isAmbiguous()) { + DiagnoseAmbiguousLookup(R, Name, NameLoc, SS.getRange()); + return DeclPtrTy(); + } + + if (R.getKind() == LookupResult::Found) + PrevDecl = dyn_cast<TagDecl>(R.getFoundDecl()); // A tag 'foo::bar' must already exist. - if (PrevDecl == 0) { + if (!PrevDecl) { Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange(); Name = 0; Invalid = true; @@ -3482,8 +4250,8 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, // FIXME: We're looking into outer scopes here, even when we // shouldn't be. Doing so can result in ambiguities that we // shouldn't be diagnosing. - LookupResult R = LookupName(S, Name, LookupTagName, - /*RedeclarationOnly=*/(TK != TK_Reference)); + LookupResult R; + LookupName(R, S, Name, LookupTagName, RedeclarationOnly); if (R.isAmbiguous()) { DiagnoseAmbiguousLookup(R, Name, NameLoc); // FIXME: This is not best way to recover from case like: @@ -3494,11 +4262,10 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, Name = 0; PrevDecl = 0; Invalid = true; - } - else - PrevDecl = R; + } else + PrevDecl = R.getAsSingleDecl(Context); - if (!getLangOptions().CPlusPlus && TK != TK_Reference) { + if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) { // FIXME: This makes sure that we ignore the contexts associated // with C structs, unions, and enums when looking for a matching // tag declaration or definition. See the similar lookup tweak @@ -3515,23 +4282,37 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, PrevDecl = 0; } + if (getLangOptions().CPlusPlus && Name && DC && StdNamespace && + DC->Equals(StdNamespace) && Name->isStr("bad_alloc")) { + // This is a declaration of or a reference to "std::bad_alloc". + isStdBadAlloc = true; + + if (!PrevDecl && StdBadAlloc) { + // std::bad_alloc has been implicitly declared (but made invisible to + // name lookup). Fill in this implicit declaration as the previous + // declaration, so that the declarations get chained appropriately. + PrevDecl = StdBadAlloc; + } + } + if (PrevDecl) { // Check whether the previous declaration is usable. (void)DiagnoseUseOfDecl(PrevDecl, NameLoc); - + if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) { // 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 || isDeclInScope(PrevDecl, SearchDC, S)) { + if (TUK == TUK_Reference || TUK == TUK_Friend || + isDeclInScope(PrevDecl, SearchDC, S)) { // Make sure that this wasn't declared as an enum and now used as a // struct or something similar. if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, KWLoc, *Name)) { - bool SafeToContinue + bool SafeToContinue = (PrevTagDecl->getTagKind() != TagDecl::TK_enum && Kind != TagDecl::TK_enum); if (SafeToContinue) - Diag(KWLoc, diag::err_use_with_wrong_tag) + Diag(KWLoc, diag::err_use_with_wrong_tag) << Name << CodeModificationHint::CreateReplacement(SourceRange(KWLoc), PrevTagDecl->getKindName()); @@ -3539,7 +4320,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, Diag(KWLoc, diag::err_use_with_wrong_tag) << Name; Diag(PrevDecl->getLocation(), diag::note_previous_use); - if (SafeToContinue) + if (SafeToContinue) Kind = PrevTagDecl->getTagKind(); else { // Recover by making this an anonymous redefinition. @@ -3556,27 +4337,35 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, // for the consumer of this Decl to know it doesn't own it. // For our current ASTs this shouldn't be a problem, but will // need to be changed with DeclGroups. - if (TK == TK_Reference) + if (TUK == TUK_Reference || TUK == TUK_Friend) return DeclPtrTy::make(PrevDecl); // Diagnose attempts to redefine a tag. - if (TK == TK_Definition) { + if (TUK == TUK_Definition) { if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) { - Diag(NameLoc, diag::err_redefinition) << Name; - Diag(Def->getLocation(), diag::note_previous_definition); - // If this is a redefinition, recover by making this - // struct be anonymous, which will make any later - // references get the previous definition. - Name = 0; - PrevDecl = 0; - Invalid = true; + // If we're defining a specialization and the previous definition + // is from an implicit instantiation, don't emit an error + // here; we'll catch this in the general case below. + if (!isExplicitSpecialization || + !isa<CXXRecordDecl>(Def) || + cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) { + Diag(NameLoc, diag::err_redefinition) << Name; + Diag(Def->getLocation(), diag::note_previous_definition); + // If this is a redefinition, recover by making this + // struct be anonymous, which will make any later + // references get the previous definition. + Name = 0; + PrevDecl = 0; + Invalid = true; + } } else { // If the type is currently being defined, complain // about a nested redefinition. TagType *Tag = cast<TagType>(Context.getTagDeclType(PrevTagDecl)); if (Tag->isBeingDefined()) { Diag(NameLoc, diag::err_nested_redefinition) << Name; - Diag(PrevTagDecl->getLocation(), + Diag(PrevTagDecl->getLocation(), diag::note_previous_definition); Name = 0; PrevDecl = 0; @@ -3589,10 +4378,11 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, } } // If we get here we have (another) forward declaration or we - // have a definition. Just create a new decl. + // have a definition. Just create a new decl. + } else { // If we get here, this is a definition of a new tag type in a nested - // scope, e.g. "struct foo; void bar() { struct foo; }", just create a + // scope, e.g. "struct foo; void bar() { struct foo; }", just create a // new decl/type. We set PrevDecl to NULL so that the entities // have distinct types. PrevDecl = 0; @@ -3617,10 +4407,10 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, PrevDecl = 0; } } - } else if (TK == TK_Reference && SS.isEmpty() && Name && + } else if (TUK == TUK_Reference && SS.isEmpty() && Name && (Kind != TagDecl::TK_enum || !getLangOptions().CPlusPlus)) { // C++ [basic.scope.pdecl]p5: - // -- for an elaborated-type-specifier of the form + // -- for an elaborated-type-specifier of the form // // class-key identifier // @@ -3641,26 +4431,38 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, // // Find the context where we'll be declaring the tag. // FIXME: We would like to maintain the current DeclContext as the - // lexical context, + // lexical context, while (SearchDC->isRecord()) SearchDC = SearchDC->getParent(); // Find the scope where we'll be declaring the tag. - while (S->isClassScope() || + while (S->isClassScope() || (getLangOptions().CPlusPlus && S->isFunctionPrototypeScope()) || ((S->getFlags() & Scope::DeclScope) == 0) || - (S->getEntity() && + (S->getEntity() && ((DeclContext *)S->getEntity())->isTransparentContext())) S = S->getParent(); + + } else if (TUK == TUK_Friend && SS.isEmpty() && Name) { + // C++ [namespace.memdef]p3: + // If a friend declaration in a non-local class first declares a + // class or function, the friend class or function is a member of + // the innermost enclosing namespace. + while (!SearchDC->isFileContext()) + SearchDC = SearchDC->getParent(); + + // The entity of a decl scope is a DeclContext; see PushDeclContext. + while (S->getEntity() != SearchDC) + S = S->getParent(); } CreateNewDecl: - + // 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, create a new declaration. If there is a previous // declaration of the same entity, the two will be linked via // PrevDecl. @@ -3669,10 +4471,10 @@ CreateNewDecl: if (Kind == TagDecl::TK_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, SearchDC, Loc, Name, + New = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc, cast_or_null<EnumDecl>(PrevDecl)); // If this is an undefined enum, warn. - if (TK != TK_Definition && !Invalid) { + if (TUK != TUK_Definition && !Invalid) { unsigned DK = getLangOptions().CPlusPlus? diag::err_forward_ref_enum : diag::ext_forward_ref_enum; Diag(Loc, DK); @@ -3682,12 +4484,15 @@ CreateNewDecl: // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: // struct X { int A; } D; D should chain to X. - if (getLangOptions().CPlusPlus) + if (getLangOptions().CPlusPlus) { // FIXME: Look for a way to use RecordDecl for simple structs. - New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, + New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, cast_or_null<CXXRecordDecl>(PrevDecl)); - else - New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, + + if (isStdBadAlloc && (!StdBadAlloc || StdBadAlloc->isImplicit())) + StdBadAlloc = cast<CXXRecordDecl>(New); + } else + New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, cast_or_null<RecordDecl>(PrevDecl)); } @@ -3704,7 +4509,7 @@ CreateNewDecl: // the #pragma tokens are effectively skipped over during the // parsing of the struct). if (unsigned Alignment = getPragmaPackAlignment()) - New->addAttr(::new (Context) PackedAttr(Alignment * 8)); + New->addAttr(::new (Context) PragmaPackAttr(Alignment * 8)); } if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) { @@ -3713,12 +4518,14 @@ CreateNewDecl: // shall not be declared with the same name as a typedef-name // that is declared in that scope and refers to a type other // than the class or enumeration itself. - LookupResult Lookup = LookupName(S, Name, LookupOrdinaryName, true); + LookupResult Lookup; + LookupName(Lookup, S, Name, LookupOrdinaryName, true); TypedefDecl *PrevTypedef = 0; - if (Lookup.getKind() == LookupResult::Found) - PrevTypedef = dyn_cast<TypedefDecl>(Lookup.getAsDecl()); + if (NamedDecl *Prev = Lookup.getAsSingleDecl(Context)) + PrevTypedef = dyn_cast<TypedefDecl>(Prev); - if (PrevTypedef && isDeclInScope(PrevTypedef, SearchDC, S) && + NamedDecl *PrevTypedefNamed = PrevTypedef; + if (PrevTypedef && isDeclInScope(PrevTypedefNamed, SearchDC, S) && Context.getCanonicalType(Context.getTypeDeclType(PrevTypedef)) != Context.getCanonicalType(Context.getTypeDeclType(New))) { Diag(Loc, diag::err_tag_definition_of_typedef) @@ -3729,6 +4536,11 @@ CreateNewDecl: } } + // If this is a specialization of a member class (of a class template), + // check the specialization. + if (isExplicitSpecialization && CheckMemberSpecialization(New, PrevDecl)) + Invalid = true; + if (Invalid) New->setInvalidDecl(); @@ -3744,21 +4556,45 @@ CreateNewDecl: // lexical context will be different from the semantic context. New->setLexicalDeclContext(CurContext); + // Mark this as a friend decl if applicable. + if (TUK == TUK_Friend) + New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ PrevDecl != NULL); + // Set the access specifier. - if (!Invalid) + if (!Invalid && TUK != TUK_Friend) SetMemberAccessSpecifier(New, PrevDecl, AS); - if (TK == TK_Definition) + if (TUK == TUK_Definition) New->startDefinition(); - + // If this has an identifier, add it to the scope stack. - if (Name) { + if (TUK == TUK_Friend) { + // We might be replacing an existing declaration in the lookup tables; + // if so, borrow its access specifier. + if (PrevDecl) + New->setAccess(PrevDecl->getAccess()); + + // Friend tag decls are visible in fairly strange ways. + if (!CurContext->isDependentContext()) { + DeclContext *DC = New->getDeclContext()->getLookupContext(); + DC->makeDeclVisibleInContext(New, /* Recoverable = */ false); + if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) + PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false); + } + } else if (Name) { S = getNonFieldDeclScope(S); PushOnScopeChains(New, S); } else { CurContext->addDecl(New); } + // If this is the C FILE type, notify the AST context. + if (IdentifierInfo *II = New->getIdentifier()) + if (!New->isInvalidDecl() && + New->getDeclContext()->getLookupContext()->isTranslationUnit() && + II->isStr("FILE")) + Context.setFILEDecl(New); + OwnedDecl = true; return DeclPtrTy::make(New); } @@ -3774,7 +4610,7 @@ void Sema::ActOnTagStartDefinition(Scope *S, DeclPtrTy TagD) { FieldCollector->StartClass(); if (Record->getIdentifier()) { - // C++ [class]p2: + // C++ [class]p2: // [...] The class-name is also inserted into the scope of the // class itself; this is known as the injected-class-name. For // purposes of access checking, the injected-class-name is treated @@ -3782,21 +4618,25 @@ void Sema::ActOnTagStartDefinition(Scope *S, DeclPtrTy TagD) { CXXRecordDecl *InjectedClassName = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext, Record->getLocation(), - Record->getIdentifier(), Record); + Record->getIdentifier(), + Record->getTagKeywordLoc(), + Record); InjectedClassName->setImplicit(); InjectedClassName->setAccess(AS_public); if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) InjectedClassName->setDescribedClassTemplate(Template); PushOnScopeChains(InjectedClassName, S); - assert(InjectedClassName->isInjectedClassName() && + assert(InjectedClassName->isInjectedClassName() && "Broken injected-class-name"); } } } -void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD) { +void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, + SourceLocation RBraceLoc) { AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>()); + Tag->setRBraceLoc(RBraceLoc); if (isa<CXXRecordDecl>(Tag)) FieldCollector->FinishClass(); @@ -3809,9 +4649,13 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD) { } // Note that FieldName may be null for anonymous bitfields. -bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, - QualType FieldTy, const Expr *BitWidth) { - +bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, + QualType FieldTy, const Expr *BitWidth, + bool *ZeroWidth) { + // Default to true; that shouldn't confuse checks for emptiness + if (ZeroWidth) + *ZeroWidth = true; + // C99 6.7.2.1p4 - verify the field type. // C++ 9.6p3: A bit-field shall have integral or enumeration type. if (!FieldTy->isDependentType() && !FieldTy->isIntegralType()) { @@ -3834,13 +4678,16 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, if (VerifyIntegerConstantExpression(BitWidth, &Value)) return true; + if (Value != 0 && ZeroWidth) + *ZeroWidth = false; + // Zero-width bitfield is ok for anonymous field. if (Value == 0 && FieldName) return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName; - + if (Value.isSigned() && Value.isNegative()) { if (FieldName) - return Diag(FieldLoc, diag::err_bitfield_has_negative_width) + return Diag(FieldLoc, diag::err_bitfield_has_negative_width) << FieldName << Value.toString(10); return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width) << Value.toString(10); @@ -3863,7 +4710,7 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, /// ActOnField - Each field of a struct/union/class is passed into this in order /// to create a FieldDecl object for it. Sema::DeclPtrTy Sema::ActOnField(Scope *S, DeclPtrTy TagD, - SourceLocation DeclStart, + SourceLocation DeclStart, Declarator &D, ExprTy *BitfieldWidth) { FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD.getAs<Decl>()), DeclStart, D, static_cast<Expr*>(BitfieldWidth), @@ -3880,8 +4727,9 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, IdentifierInfo *II = D.getIdentifier(); SourceLocation Loc = DeclStart; if (II) Loc = D.getIdentifierLoc(); - - QualType T = GetTypeForDeclarator(D, S); + + DeclaratorInfo *DInfo = 0; + QualType T = GetTypeForDeclarator(D, S, &DInfo); if (getLangOptions().CPlusPlus) CheckExtraCXXDefaultArguments(D); @@ -3890,7 +4738,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); - NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true); + NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, true); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. @@ -3902,10 +4750,12 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) PrevDecl = 0; - FieldDecl *NewFD - = CheckFieldDecl(II, T, Record, Loc, - D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable, - BitWidth, AS, PrevDecl, &D); + bool Mutable + = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable); + SourceLocation TSSL = D.getSourceRange().getBegin(); + FieldDecl *NewFD + = CheckFieldDecl(II, T, DInfo, Record, Loc, Mutable, BitWidth, TSSL, + AS, PrevDecl, &D); if (NewFD->isInvalidDecl() && PrevDecl) { // Don't introduce NewFD into scope; there's already something // with the same name in the same scope. @@ -3926,10 +4776,12 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, /// /// \returns a new FieldDecl. /// -/// \todo The Declarator argument is a hack. It will be removed once -FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, +/// \todo The Declarator argument is a hack. It will be removed once +FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, + DeclaratorInfo *DInfo, RecordDecl *Record, SourceLocation Loc, - bool Mutable, Expr *BitWidth, + bool Mutable, Expr *BitWidth, + SourceLocation TSSL, AccessSpecifier AS, NamedDecl *PrevDecl, Declarator *D) { IdentifierInfo *II = Name.getAsIdentifierInfo(); @@ -3957,25 +4809,26 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, Diag(Loc, diag::err_typecheck_negative_array_size); else Diag(Loc, diag::err_typecheck_field_variable_size); - T = Context.IntTy; InvalidDecl = true; } } - + // Fields can not have abstract class types - if (RequireNonAbstractType(Loc, T, diag::err_abstract_type_in_decl, + if (RequireNonAbstractType(Loc, T, diag::err_abstract_type_in_decl, AbstractFieldType)) InvalidDecl = true; - + + bool ZeroWidth = false; // If this is declared as a bit-field, check the bit-field. - if (BitWidth && VerifyBitField(Loc, II, T, BitWidth)) { + if (BitWidth && VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) { InvalidDecl = true; DeleteExpr(BitWidth); BitWidth = 0; + ZeroWidth = false; } - - FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, BitWidth, - Mutable); + + FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, DInfo, + BitWidth, Mutable); if (InvalidDecl) NewFD->setInvalidDecl(); @@ -3985,8 +4838,61 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, NewFD->setInvalidDecl(); } - if (getLangOptions().CPlusPlus && !T->isPODType()) - cast<CXXRecordDecl>(Record)->setPOD(false); + if (getLangOptions().CPlusPlus) { + QualType EltTy = Context.getBaseElementType(T); + + CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record); + + if (!T->isPODType()) + CXXRecord->setPOD(false); + if (!ZeroWidth) + CXXRecord->setEmpty(false); + + if (const RecordType *RT = EltTy->getAs<RecordType>()) { + CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl()); + + if (!RDecl->hasTrivialConstructor()) + CXXRecord->setHasTrivialConstructor(false); + if (!RDecl->hasTrivialCopyConstructor()) + CXXRecord->setHasTrivialCopyConstructor(false); + if (!RDecl->hasTrivialCopyAssignment()) + CXXRecord->setHasTrivialCopyAssignment(false); + if (!RDecl->hasTrivialDestructor()) + CXXRecord->setHasTrivialDestructor(false); + + // C++ 9.5p1: An object of a class with a non-trivial + // constructor, a non-trivial copy constructor, a non-trivial + // destructor, or a non-trivial copy assignment operator + // cannot be a member of a union, nor can an array of such + // objects. + // TODO: C++0x alters this restriction significantly. + if (Record->isUnion()) { + // We check for copy constructors before constructors + // because otherwise we'll never get complaints about + // copy constructors. + + const CXXSpecialMember invalid = (CXXSpecialMember) -1; + + CXXSpecialMember member; + if (!RDecl->hasTrivialCopyConstructor()) + member = CXXCopyConstructor; + else if (!RDecl->hasTrivialConstructor()) + member = CXXDefaultConstructor; + else if (!RDecl->hasTrivialCopyAssignment()) + member = CXXCopyAssignment; + else if (!RDecl->hasTrivialDestructor()) + member = CXXDestructor; + else + member = invalid; + + if (member != invalid) { + Diag(Loc, diag::err_illegal_union_member) << Name << member; + DiagnoseNontrivial(RT, member); + NewFD->setInvalidDecl(); + } + } + } + } // FIXME: We need to pass in the attributes given an AST // representation, not a parser representation. @@ -4013,7 +4919,131 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, return NewFD; } -/// TranslateIvarVisibility - Translate visibility from a token ID to an +/// DiagnoseNontrivial - Given that a class has a non-trivial +/// special member, figure out why. +void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { + QualType QT(T, 0U); + CXXRecordDecl* RD = cast<CXXRecordDecl>(T->getDecl()); + + // Check whether the member was user-declared. + switch (member) { + case CXXDefaultConstructor: + if (RD->hasUserDeclaredConstructor()) { + typedef CXXRecordDecl::ctor_iterator ctor_iter; + for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce; ++ci) + if (!ci->isImplicitlyDefined(Context)) { + SourceLocation CtorLoc = ci->getLocation(); + Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + + assert(0 && "found no user-declared constructors"); + return; + } + break; + + case CXXCopyConstructor: + if (RD->hasUserDeclaredCopyConstructor()) { + SourceLocation CtorLoc = + RD->getCopyConstructor(Context, 0)->getLocation(); + Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + + case CXXCopyAssignment: + if (RD->hasUserDeclaredCopyAssignment()) { + // FIXME: this should use the location of the copy + // assignment, not the type. + SourceLocation TyLoc = RD->getSourceRange().getBegin(); + Diag(TyLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + + case CXXDestructor: + if (RD->hasUserDeclaredDestructor()) { + SourceLocation DtorLoc = RD->getDestructor(Context)->getLocation(); + Diag(DtorLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + } + + typedef CXXRecordDecl::base_class_iterator base_iter; + + // Virtual bases and members inhibit trivial copying/construction, + // but not trivial destruction. + if (member != CXXDestructor) { + // Check for virtual bases. vbases includes indirect virtual bases, + // so we just iterate through the direct bases. + for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) + if (bi->isVirtual()) { + SourceLocation BaseLoc = bi->getSourceRange().getBegin(); + Diag(BaseLoc, diag::note_nontrivial_has_virtual) << QT << 1; + return; + } + + // Check for virtual methods. + typedef CXXRecordDecl::method_iterator meth_iter; + for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; + ++mi) { + if (mi->isVirtual()) { + SourceLocation MLoc = mi->getSourceRange().getBegin(); + Diag(MLoc, diag::note_nontrivial_has_virtual) << QT << 0; + return; + } + } + } + + bool (CXXRecordDecl::*hasTrivial)() const; + switch (member) { + case CXXDefaultConstructor: + hasTrivial = &CXXRecordDecl::hasTrivialConstructor; break; + case CXXCopyConstructor: + hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break; + case CXXCopyAssignment: + hasTrivial = &CXXRecordDecl::hasTrivialCopyAssignment; break; + case CXXDestructor: + hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break; + default: + assert(0 && "unexpected special member"); return; + } + + // Check for nontrivial bases (and recurse). + for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) { + const RecordType *BaseRT = bi->getType()->getAs<RecordType>(); + assert(BaseRT); + CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl()); + if (!(BaseRecTy->*hasTrivial)()) { + SourceLocation BaseLoc = bi->getSourceRange().getBegin(); + Diag(BaseLoc, diag::note_nontrivial_has_nontrivial) << QT << 1 << member; + DiagnoseNontrivial(BaseRT, member); + return; + } + } + + // Check for nontrivial members (and recurse). + typedef RecordDecl::field_iterator field_iter; + for (field_iter fi = RD->field_begin(), fe = RD->field_end(); fi != fe; + ++fi) { + QualType EltTy = Context.getBaseElementType((*fi)->getType()); + if (const RecordType *EltRT = EltTy->getAs<RecordType>()) { + CXXRecordDecl* EltRD = cast<CXXRecordDecl>(EltRT->getDecl()); + + if (!(EltRD->*hasTrivial)()) { + SourceLocation FLoc = (*fi)->getLocation(); + Diag(FLoc, diag::note_nontrivial_has_nontrivial) << QT << 0 << member; + DiagnoseNontrivial(EltRT, member); + return; + } + } + } + + assert(0 && "found no explanation for non-trivial member"); +} + +/// TranslateIvarVisibility - Translate visibility from a token ID to an /// AST enum value. static ObjCIvarDecl::AccessControl TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { @@ -4026,24 +5056,25 @@ TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { } } -/// ActOnIvar - Each ivar field of an objective-c class is passed into this +/// ActOnIvar - Each ivar field of an objective-c class is passed into this /// in order to create an IvarDecl object for it. Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, - SourceLocation DeclStart, + SourceLocation DeclStart, DeclPtrTy IntfDecl, Declarator &D, ExprTy *BitfieldWidth, tok::ObjCKeywordKind Visibility) { - + 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! - - QualType T = GetTypeForDeclarator(D, S); - + + DeclaratorInfo *DInfo = 0; + QualType T = GetTypeForDeclarator(D, S, &DInfo); + if (BitWidth) { // 6.7.2.1p3, 6.7.2.1p4 if (VerifyBitField(Loc, II, T, BitWidth)) { @@ -4053,43 +5084,42 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, } } else { // Not a bitfield. - + // validate II. - + } - + // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. if (T->isVariablyModifiedType()) { Diag(Loc, diag::err_typecheck_ivar_variable_size); D.setInvalidType(); } - + // Get the visibility (access control) for this ivar. - ObjCIvarDecl::AccessControl ac = + ObjCIvarDecl::AccessControl ac = Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) : ObjCIvarDecl::None; // Must set ivar's DeclContext to its enclosing interface. Decl *EnclosingDecl = IntfDecl.getAs<Decl>(); DeclContext *EnclosingContext; - if (ObjCImplementationDecl *IMPDecl = + if (ObjCImplementationDecl *IMPDecl = dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { // Case of ivar declared in an implementation. Context is that of its class. ObjCInterfaceDecl* IDecl = IMPDecl->getClassInterface(); assert(IDecl && "No class- ActOnIvar"); EnclosingContext = cast_or_null<DeclContext>(IDecl); - } - else + } else EnclosingContext = dyn_cast<DeclContext>(EnclosingDecl); assert(EnclosingContext && "null DeclContext for ivar - ActOnIvar"); - + // Construct the decl. - ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, - EnclosingContext, Loc, II, T,ac, - (Expr *)BitfieldWidth); - + ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, + EnclosingContext, Loc, II, T, + DInfo, ac, (Expr *)BitfieldWidth); + if (II) { - NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true); + NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, true); if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S) && !isa<TagDecl>(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; @@ -4100,7 +5130,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, // Process attributes attached to the ivar. ProcessDeclAttributes(S, NewID, D); - + if (D.isInvalidType()) NewID->setInvalidDecl(); @@ -4121,7 +5151,7 @@ void Sema::ActOnFields(Scope* S, AttributeList *Attr) { Decl *EnclosingDecl = RecDecl.getAs<Decl>(); assert(EnclosingDecl && "missing record or interface decl"); - + // If the decl this is being inserted into is invalid, then it may be a // redeclaration or some other bogus case. Don't try to add fields to it. if (EnclosingDecl->isInvalidDecl()) { @@ -4129,7 +5159,7 @@ void Sema::ActOnFields(Scope* S, return; } - + // Verify that all the fields are okay. unsigned NumNamedMembers = 0; llvm::SmallVector<FieldDecl*, 32> RecFields; @@ -4137,7 +5167,7 @@ void Sema::ActOnFields(Scope* S, RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl); for (unsigned i = 0; i != NumFields; ++i) { FieldDecl *FD = cast<FieldDecl>(Fields[i].getAs<Decl>()); - + // Get the type for the field. Type *FDTy = FD->getType().getTypePtr(); @@ -4145,12 +5175,12 @@ void Sema::ActOnFields(Scope* S, // Remember all fields written by the user. RecFields.push_back(FD); } - + // If the field is already invalid for some reason, don't emit more // diagnostics about it. if (FD->isInvalidDecl()) continue; - + // C99 6.7.2.1p2: // A structure or union shall not contain a member with // incomplete or function type (hence, a structure shall not @@ -4182,13 +5212,13 @@ void Sema::ActOnFields(Scope* S, if (Record) Record->setHasFlexibleArrayMember(true); } else if (!FDTy->isDependentType() && - RequireCompleteType(FD->getLocation(), FD->getType(), + RequireCompleteType(FD->getLocation(), FD->getType(), diag::err_field_incomplete)) { // Incomplete type FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); continue; - } else if (const RecordType *FDTTy = FDTy->getAsRecordType()) { + } else if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) { if (FDTTy->getDecl()->hasFlexibleArrayMember()) { // If this is a member of a union, then entire union becomes "flexible". if (Record && Record->isUnion()) { @@ -4210,13 +5240,20 @@ void Sema::ActOnFields(Scope* S, } } } + if (Record && FDTTy->getDecl()->hasObjectMember()) + Record->setHasObjectMember(true); } else if (FDTy->isObjCInterfaceType()) { /// A field cannot be an Objective-c object Diag(FD->getLocation(), diag::err_statically_allocated_object); FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); continue; - } + } else if (getLangOptions().ObjC1 && + getLangOptions().getGCMode() != LangOptions::NonGC && + Record && + (FD->getType()->isObjCObjectPointerType() || + FD->getType().isObjCGCStrong())) + Record->setHasObjectMember(true); // Keep track of the number of named members. if (FD->getIdentifier()) ++NumNamedMembers; @@ -4239,7 +5276,7 @@ void Sema::ActOnFields(Scope* S, // Must enforce the rule that ivars in the base classes may not be // duplicates. if (ID->getSuperClass()) { - for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(), + for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(), IVE = ID->ivar_end(); IVI != IVE; ++IVI) { ObjCIvarDecl* Ivar = (*IVI); @@ -4253,7 +5290,7 @@ void Sema::ActOnFields(Scope* S, } } } - } else if (ObjCImplementationDecl *IMPDecl = + } else if (ObjCImplementationDecl *IMPDecl = dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl"); for (unsigned I = 0, N = RecFields.size(); I != N; ++I) @@ -4294,7 +5331,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, EltTy = Val->getType(); } } - + if (!Val) { if (LastEnumConst) { // Assign the last value + 1. @@ -4304,7 +5341,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // 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. @@ -4312,10 +5349,10 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy))); } } - + val.release(); return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, - Val, EnumVal); + Val, EnumVal); } @@ -4332,10 +5369,10 @@ Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl, // The scope passed in may not be a decl scope. Zip up the scope tree until // we find one that is. S = getNonFieldDeclScope(S); - + // Verify that there isn't already something declared with this name in this // scope. - NamedDecl *PrevDecl = LookupName(S, Id, LookupOrdinaryName); + NamedDecl *PrevDecl = LookupSingleName(S, Id, LookupOrdinaryName); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(IdLoc, PrevDecl); @@ -4371,28 +5408,34 @@ Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl, void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, SourceLocation RBraceLoc, DeclPtrTy EnumDeclX, - DeclPtrTy *Elements, unsigned NumElements) { + DeclPtrTy *Elements, unsigned NumElements, + Scope *S, AttributeList *Attr) { EnumDecl *Enum = cast<EnumDecl>(EnumDeclX.getAs<Decl>()); QualType EnumType = Context.getTypeDeclType(Enum); - + + if (Attr) + ProcessDeclAttributeList(S, Enum, Attr); + // 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(); - + unsigned CharWidth = Context.Target.getCharWidth(); + unsigned ShortWidth = Context.Target.getShortWidth(); + // 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; - + for (unsigned i = 0; i != NumElements; ++i) { EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>()); 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 && @@ -4405,7 +5448,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, Diag(ECD->getLocation(), diag::ext_enum_value_not_int) << InitVal.toString(10); } - + // Keep track of the size of positive and negative values. if (InitVal.isUnsigned() || InitVal.isNonNegative()) NumPositiveBits = std::max(NumPositiveBits, @@ -4416,28 +5459,39 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // Keep track of whether every enum element has type int (very commmon). if (AllElementsInt) - AllElementsInt = ECD->getType() == Context.IntTy; + AllElementsInt = ECD->getType() == Context.IntTy; } - + // Figure out the type that should be used for this enum. - // FIXME: Support attribute(packed) on enums and -fshort-enums. + // FIXME: Support -fshort-enums. QualType BestType; unsigned BestWidth; - + + bool Packed = Enum->getAttr<PackedAttr>() ? true : false; + if (NumNegativeBits) { - // If there is a negative value, figure out the smallest integer type (of + // If there is a negative value, figure out the smallest integer type (of // int/long/longlong) that fits. - if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) { + // If it's packed, check also if it fits a char or a short. + if (Packed && NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) { + BestType = Context.SignedCharTy; + BestWidth = CharWidth; + } else if (Packed && NumNegativeBits <= ShortWidth && + NumPositiveBits < ShortWidth) { + BestType = Context.ShortTy; + BestWidth = ShortWidth; + } + else 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; @@ -4446,7 +5500,15 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, } else { // If there is no negative value, figure out which of uint, ulong, ulonglong // fits. - if (NumPositiveBits <= IntWidth) { + // If it's packed, check also if it fits a char or a short. + if (Packed && NumPositiveBits <= CharWidth) { + BestType = Context.UnsignedCharTy; + BestWidth = CharWidth; + } else if (Packed && NumPositiveBits <= ShortWidth) { + BestType = Context.UnsignedShortTy; + BestWidth = ShortWidth; + } + else if (NumPositiveBits <= IntWidth) { BestType = Context.UnsignedIntTy; BestWidth = IntWidth; } else if (NumPositiveBits <= @@ -4459,7 +5521,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, 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) { @@ -4481,7 +5543,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, if (getLangOptions().CPlusPlus) // C++ [dcl.enum]p4: Following the closing brace of an // enum-specifier, each enumerator has the type of its - // enumeration. + // enumeration. ECD->setType(EnumType); continue; // Already int type. } @@ -4508,7 +5570,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, if (getLangOptions().CPlusPlus) // C++ [dcl.enum]p4: Following the closing brace of an // enum-specifier, each enumerator has the type of its - // enumeration. + // enumeration. ECD->setType(EnumType); continue; } else { @@ -4521,20 +5583,22 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, InitVal.extOrTrunc(NewWidth); InitVal.setIsSigned(NewSign); ECD->setInitVal(InitVal); - + // Adjust the Expr initializer and type. if (ECD->getInitExpr()) - ECD->setInitExpr(new (Context) ImplicitCastExpr(NewTy, ECD->getInitExpr(), + ECD->setInitExpr(new (Context) ImplicitCastExpr(NewTy, + CastExpr::CK_Unknown, + ECD->getInitExpr(), /*isLvalue=*/false)); if (getLangOptions().CPlusPlus) // C++ [dcl.enum]p4: Following the closing brace of an // enum-specifier, each enumerator has the type of its - // enumeration. + // enumeration. ECD->setType(EnumType); else ECD->setType(NewTy); } - + Enum->completeDefinition(Context, BestType); } @@ -4551,15 +5615,15 @@ Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, SourceLocation PragmaLoc, SourceLocation NameLoc) { - Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName); + Decl *PrevDecl = LookupSingleName(TUScope, Name, LookupOrdinaryName); - // FIXME: This implementation is an ugly hack! if (PrevDecl) { PrevDecl->addAttr(::new (Context) WeakAttr()); - return; + } else { + (void)WeakUndeclaredIdentifiers.insert( + std::pair<IdentifierInfo*,WeakInfo> + (Name, WeakInfo((IdentifierInfo*)0, NameLoc))); } - Diag(PragmaLoc, diag::err_unsupported_pragma_weak); - return; } void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, @@ -4567,14 +5631,15 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, SourceLocation PragmaLoc, SourceLocation NameLoc, SourceLocation AliasNameLoc) { - Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName); + Decl *PrevDecl = LookupSingleName(TUScope, AliasName, LookupOrdinaryName); + WeakInfo W = WeakInfo(Name, NameLoc); - // FIXME: This implementation is an ugly hack! if (PrevDecl) { - PrevDecl->addAttr(::new (Context) AliasAttr(AliasName->getName())); - PrevDecl->addAttr(::new (Context) WeakAttr()); - return; + if (!PrevDecl->hasAttr<AliasAttr>()) + if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl)) + DeclApplyPragmaWeak(TUScope, ND, W); + } else { + (void)WeakUndeclaredIdentifiers.insert( + std::pair<IdentifierInfo*,WeakInfo>(AliasName, W)); } - Diag(PragmaLoc, diag::err_unsupported_pragma_weak); - return; } |