diff options
author | dim <dim@FreeBSD.org> | 2011-05-02 19:39:53 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-05-02 19:39:53 +0000 |
commit | 110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab (patch) | |
tree | 64a10f4c4154739d4a8191d7e1b52ce497f4ebd6 /lib/Sema/SemaDecl.cpp | |
parent | a0fb00f9837bd0d2e5948f16f6a6b82a7a628f51 (diff) | |
download | FreeBSD-src-110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab.zip FreeBSD-src-110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab.tar.gz |
Vendor import of clang trunk r130700:
http://llvm.org/svn/llvm-project/cfe/trunk@130700
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 1222 |
1 files changed, 947 insertions, 275 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d6efd7a..7214988 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -17,6 +17,7 @@ #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "TypeLocBuilder.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -24,6 +25,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/CharUnits.h" @@ -61,7 +63,8 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr) { ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS, bool isClassName, bool HasTrailingDot, - ParsedType ObjectTypePtr) { + ParsedType ObjectTypePtr, + bool WantNontrivialTypeSourceInfo) { // Determine where we will perform name lookup. DeclContext *LookupCtx = 0; if (ObjectTypePtr) { @@ -87,10 +90,15 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // We know from the grammar that this name refers to a type, // so build a dependent node to describe the type. + if (WantNontrivialTypeSourceInfo) + return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get(); + + NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context); QualType T = - CheckTypenameType(ETK_None, SS->getScopeRep(), II, - SourceLocation(), SS->getRange(), NameLoc); - return ParsedType::make(T); + CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc, + II, NameLoc); + + return ParsedType::make(T); } return ParsedType(); @@ -189,10 +197,23 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, if (T.isNull()) T = Context.getTypeDeclType(TD); - if (SS) - T = getElaboratedType(ETK_None, *SS, T); - + if (SS && SS->isNotEmpty()) { + if (WantNontrivialTypeSourceInfo) { + // Construct a type with type-source information. + TypeLocBuilder Builder; + Builder.pushTypeSpec(T).setNameLoc(NameLoc); + + T = getElaboratedType(ETK_None, *SS, T); + ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T); + ElabTL.setKeywordLoc(SourceLocation()); + ElabTL.setQualifierLoc(SS->getWithLocInContext(Context)); + return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); + } else { + T = getElaboratedType(ETK_None, *SS, T); + } + } } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { + (void)DiagnoseUseOfDecl(IDecl, NameLoc); if (!HasTrailingDot) T = Context.getObjCInterfaceType(IDecl); } @@ -229,6 +250,33 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { return DeclSpec::TST_unspecified; } +/// isMicrosoftMissingTypename - In Microsoft mode, within class scope, +/// if a CXXScopeSpec's type is equal to the type of one of the base classes +/// then downgrade the missing typename error to a warning. +/// This is needed for MSVC compatibility; Example: +/// @code +/// template<class T> class A { +/// public: +/// typedef int TYPE; +/// }; +/// template<class T> class B : public A<T> { +/// public: +/// A<T>::TYPE a; // no typename required because A<T> is a base class. +/// }; +/// @endcode +bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS) { + if (CurContext->isRecord()) { + const Type *Ty = SS->getScopeRep()->getAsType(); + + CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext); + for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(), + BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) + if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType())) + return true; + } + return false; +} + bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, @@ -263,7 +311,9 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, Diag(Result->getLocation(), diag::note_previous_decl) << Result->getDeclName(); - SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS); + SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS, + false, false, ParsedType(), + /*NonTrivialTypeSourceInfo=*/true); return true; } } else if (Lookup.empty()) { @@ -304,7 +354,11 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, Diag(IILoc, diag::err_typename_nested_not_found) << &II << DC << SS->getRange(); else if (isDependentScopeSpecifier(*SS)) { - Diag(SS->getRange().getBegin(), diag::err_typename_missing) + unsigned DiagID = diag::err_typename_missing; + if (getLangOptions().Microsoft && isMicrosoftMissingTypename(SS)) + DiagID = diag::warn_typename_missing; + + Diag(SS->getRange().getBegin(), DiagID) << (NestedNameSpecifier *)SS->getScopeRep() << II.getName() << SourceRange(SS->getRange().getBegin(), IILoc) << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); @@ -317,6 +371,328 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, return true; } +/// \brief Determine whether the given result set contains either a type name +/// or +static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) { + bool CheckTemplate = R.getSema().getLangOptions().CPlusPlus && + NextToken.is(tok::less); + + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) { + if (isa<TypeDecl>(*I) || isa<ObjCInterfaceDecl>(*I)) + return true; + + if (CheckTemplate && isa<TemplateDecl>(*I)) + return true; + } + + return false; +} + +Sema::NameClassification Sema::ClassifyName(Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *&Name, + SourceLocation NameLoc, + const Token &NextToken) { + DeclarationNameInfo NameInfo(Name, NameLoc); + ObjCMethodDecl *CurMethod = getCurMethodDecl(); + + if (NextToken.is(tok::coloncolon)) { + BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(), + QualType(), false, SS, 0, false); + + } + + LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); + LookupParsedName(Result, S, &SS, !CurMethod); + + // Perform lookup for Objective-C instance variables (including automatically + // synthesized instance variables), if we're in an Objective-C method. + // FIXME: This lookup really, really needs to be folded in to the normal + // unqualified lookup mechanism. + if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { + ExprResult E = LookupInObjCMethod(Result, S, Name, true); + if (E.get() || E.isInvalid()) + return E; + + // Synthesize ivars lazily. + if (getLangOptions().ObjCDefaultSynthProperties && + getLangOptions().ObjCNonFragileABI2) { + if (SynthesizeProvisionalIvar(Result, Name, NameLoc)) { + if (const ObjCPropertyDecl *Property = + canSynthesizeProvisionalIvar(Name)) { + Diag(NameLoc, diag::warn_synthesized_ivar_access) << Name; + Diag(Property->getLocation(), diag::note_property_declare); + } + + // FIXME: This is strange. Shouldn't we just take the ivar returned + // from SynthesizeProvisionalIvar and continue with that? + E = LookupInObjCMethod(Result, S, Name, true); + if (E.get() || E.isInvalid()) + return E; + } + } + } + + bool SecondTry = false; + bool IsFilteredTemplateName = false; + +Corrected: + switch (Result.getResultKind()) { + case LookupResult::NotFound: + // If an unqualified-id is followed by a '(', then we have a function + // call. + if (!SS.isSet() && NextToken.is(tok::l_paren)) { + // In C++, this is an ADL-only call. + // FIXME: Reference? + if (getLangOptions().CPlusPlus) + return BuildDeclarationNameExpr(SS, Result, /*ADL=*/true); + + // C90 6.3.2.2: + // If the expression that precedes the parenthesized argument list in a + // function call consists solely of an identifier, and if no + // declaration is visible for this identifier, the identifier is + // implicitly declared exactly as if, in the innermost block containing + // the function call, the declaration + // + // extern int identifier (); + // + // appeared. + // + // We also allow this in C99 as an extension. + if (NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *Name, S)) { + Result.addDecl(D); + Result.resolveKind(); + return BuildDeclarationNameExpr(SS, Result, /*ADL=*/false); + } + } + + // In C, we first see whether there is a tag type by the same name, in + // which case it's likely that the user just forget to write "enum", + // "struct", or "union". + if (!getLangOptions().CPlusPlus && !SecondTry) { + Result.clear(LookupTagName); + LookupParsedName(Result, S, &SS); + if (TagDecl *Tag = Result.getAsSingle<TagDecl>()) { + const char *TagName = 0; + const char *FixItTagName = 0; + switch (Tag->getTagKind()) { + case TTK_Class: + TagName = "class"; + FixItTagName = "class "; + break; + + case TTK_Enum: + TagName = "enum"; + FixItTagName = "enum "; + break; + + case TTK_Struct: + TagName = "struct"; + FixItTagName = "struct "; + break; + + case TTK_Union: + TagName = "union"; + FixItTagName = "union "; + break; + } + + Diag(NameLoc, diag::err_use_of_tag_name_without_tag) + << Name << TagName << getLangOptions().CPlusPlus + << FixItHint::CreateInsertion(NameLoc, FixItTagName); + break; + } + + Result.clear(LookupOrdinaryName); + } + + // Perform typo correction to determine if there is another name that is + // close to this name. + if (!SecondTry) { + if (DeclarationName Corrected = CorrectTypo(Result, S, &SS)) { + unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; + unsigned QualifiedDiag = diag::err_no_member_suggest; + + NamedDecl *FirstDecl = Result.empty()? 0 : *Result.begin(); + NamedDecl *UnderlyingFirstDecl + = FirstDecl? FirstDecl->getUnderlyingDecl() : 0; + if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) { + UnqualifiedDiag = diag::err_no_template_suggest; + QualifiedDiag = diag::err_no_member_template_suggest; + } else if (UnderlyingFirstDecl && + (isa<TypeDecl>(UnderlyingFirstDecl) || + isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) || + isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) { + UnqualifiedDiag = diag::err_unknown_typename_suggest; + QualifiedDiag = diag::err_unknown_nested_typename_suggest; + } + + if (SS.isEmpty()) + Diag(NameLoc, UnqualifiedDiag) + << Name << Corrected + << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString()); + else + Diag(NameLoc, QualifiedDiag) + << Name << computeDeclContext(SS, false) << Corrected + << SS.getRange() + << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString()); + + // Update the name, so that the caller has the new name. + Name = Corrected.getAsIdentifierInfo(); + + // Typo correction corrected to a keyword. + if (Result.empty()) + return Corrected.getAsIdentifierInfo(); + + Diag(FirstDecl->getLocation(), diag::note_previous_decl) + << FirstDecl->getDeclName(); + + // If we found an Objective-C instance variable, let + // LookupInObjCMethod build the appropriate expression to + // reference the ivar. + // FIXME: This is a gross hack. + if (ObjCIvarDecl *Ivar = Result.getAsSingle<ObjCIvarDecl>()) { + Result.clear(); + ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier())); + return move(E); + } + + goto Corrected; + } + } + + // We failed to correct; just fall through and let the parser deal with it. + Result.suppressDiagnostics(); + return NameClassification::Unknown(); + + case LookupResult::NotFoundInCurrentInstantiation: + // We performed name lookup into the current instantiation, and there were + // dependent bases, so we treat this result the same way as any other + // dependent nested-name-specifier. + + // C++ [temp.res]p2: + // A name used in a template declaration or definition and that is + // dependent on a template-parameter is assumed not to name a type + // unless the applicable name lookup finds a type name or the name is + // qualified by the keyword typename. + // + // FIXME: If the next token is '<', we might want to ask the parser to + // perform some heroics to see if we actually have a + // template-argument-list, which would indicate a missing 'template' + // keyword here. + return BuildDependentDeclRefExpr(SS, NameInfo, /*TemplateArgs=*/0); + + case LookupResult::Found: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + break; + + case LookupResult::Ambiguous: + if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + hasAnyAcceptableTemplateNames(Result)) { + // C++ [temp.local]p3: + // A lookup that finds an injected-class-name (10.2) can result in an + // ambiguity in certain cases (for example, if it is found in more than + // one base class). If all of the injected-class-names that are found + // refer to specializations of the same class template, and if the name + // is followed by a template-argument-list, the reference refers to the + // class template itself and not a specialization thereof, and is not + // ambiguous. + // + // This filtering can make an ambiguous result into an unambiguous one, + // so try again after filtering out template names. + FilterAcceptableTemplateNames(Result); + if (!Result.isAmbiguous()) { + IsFilteredTemplateName = true; + break; + } + } + + // Diagnose the ambiguity and return an error. + return NameClassification::Error(); + } + + if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + (IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) { + // C++ [temp.names]p3: + // After name lookup (3.4) finds that a name is a template-name or that + // an operator-function-id or a literal- operator-id refers to a set of + // overloaded functions any member of which is a function template if + // this is followed by a <, the < is always taken as the delimiter of a + // template-argument-list and never as the less-than operator. + if (!IsFilteredTemplateName) + FilterAcceptableTemplateNames(Result); + + if (!Result.empty()) { + bool IsFunctionTemplate; + TemplateName Template; + if (Result.end() - Result.begin() > 1) { + IsFunctionTemplate = true; + Template = Context.getOverloadedTemplateName(Result.begin(), + Result.end()); + } else { + TemplateDecl *TD + = cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl()); + IsFunctionTemplate = isa<FunctionTemplateDecl>(TD); + + if (SS.isSet() && !SS.isInvalid()) + Template = Context.getQualifiedTemplateName(SS.getScopeRep(), + /*TemplateKeyword=*/false, + TD); + else + Template = TemplateName(TD); + } + + if (IsFunctionTemplate) { + // Function templates always go through overload resolution, at which + // point we'll perform the various checks (e.g., accessibility) we need + // to based on which function we selected. + Result.suppressDiagnostics(); + + return NameClassification::FunctionTemplate(Template); + } + + return NameClassification::TypeTemplate(Template); + } + } + + NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); + if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) { + DiagnoseUseOfDecl(Type, NameLoc); + QualType T = Context.getTypeDeclType(Type); + return ParsedType::make(T); + } + + ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl); + if (!Class) { + // FIXME: It's unfortunate that we don't have a Type node for handling this. + if (ObjCCompatibleAliasDecl *Alias + = dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl)) + Class = Alias->getClassInterface(); + } + + if (Class) { + DiagnoseUseOfDecl(Class, NameLoc); + + if (NextToken.is(tok::period)) { + // Interface. <something> is parsed as a property reference expression. + // Just return "unknown" as a fall-through for now. + Result.suppressDiagnostics(); + return NameClassification::Unknown(); + } + + QualType T = Context.getObjCInterfaceType(Class); + return ParsedType::make(T); + } + + if (!Result.empty() && (*Result.begin())->isCXXClassMember()) + return BuildPossibleImplicitMemberExpr(SS, Result, 0); + + bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); + return BuildDeclarationNameExpr(SS, Result, ADL); +} + // 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. @@ -472,11 +848,30 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { } S->AddDecl(D); - IdResolver.AddDecl(D); + + if (isa<LabelDecl>(D) && !cast<LabelDecl>(D)->isGnuLocal()) { + // Implicitly-generated labels may end up getting generated in an order that + // isn't strictly lexical, which breaks name lookup. Be careful to insert + // the label at the appropriate place in the identifier chain. + for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) { + DeclContext *IDC = (*I)->getLexicalDeclContext()->getRedeclContext(); + if (IDC == CurContext) { + if (!S->isDeclScope(*I)) + continue; + } else if (IDC->Encloses(CurContext)) + break; + } + + IdResolver.InsertDeclAfter(I, D); + } else { + IdResolver.AddDecl(D); + } } -bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) { - return IdResolver.isDeclInScope(D, Ctx, Context, S); +bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, + bool ExplicitInstantiationOrSpecialization) { + return IdResolver.isDeclInScope(D, Ctx, Context, S, + ExplicitInstantiationOrSpecialization); } Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) { @@ -498,12 +893,13 @@ static bool isOutOfScopePreviousDeclaration(NamedDecl *, /// as determined by isDeclInScope. static void FilterLookupForScope(Sema &SemaRef, LookupResult &R, DeclContext *Ctx, Scope *S, - bool ConsiderLinkage) { + bool ConsiderLinkage, + bool ExplicitInstantiationOrSpecialization) { LookupResult::Filter F = R.makeFilter(); while (F.hasNext()) { NamedDecl *D = F.next(); - if (SemaRef.isDeclInScope(D, Ctx, S)) + if (SemaRef.isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization)) continue; if (ConsiderLinkage && @@ -841,7 +1237,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, FunctionDecl *New = FunctionDecl::Create(Context, Context.getTranslationUnitDecl(), - Loc, II, R, /*TInfo=*/0, + Loc, Loc, II, R, /*TInfo=*/0, SC_Extern, SC_None, false, /*hasPrototype=*/true); @@ -851,10 +1247,15 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, // FunctionDecl. if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) { llvm::SmallVector<ParmVarDecl*, 16> Params; - for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) - Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0, - FT->getArgType(i), /*TInfo=*/0, - SC_None, SC_None, 0)); + for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { + ParmVarDecl *parm = + ParmVarDecl::Create(Context, New, SourceLocation(), + SourceLocation(), 0, + FT->getArgType(i), /*TInfo=*/0, + SC_None, SC_None, 0); + parm->setScopeInfo(0, i); + Params.push_back(parm); + } New->setParams(Params.data(), Params.size()); } @@ -871,12 +1272,12 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, return New; } -/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the +/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the /// same name and scope as a previous declaration 'Old'. Figure out /// how to resolve this situation, merging decls or emitting /// diagnostics as appropriate. If there was an error, set New to be invalid. /// -void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { +void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { // If the new decl is known invalid already, don't bother doing any // merging checks. if (New->isInvalidDecl()) return; @@ -936,7 +1337,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // Determine the "old" type we'll use for checking and diagnostics. QualType OldType; - if (TypedefDecl *OldTypedef = dyn_cast<TypedefDecl>(Old)) + if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old)) OldType = OldTypedef->getUnderlyingType(); else OldType = Context.getTypeDeclType(Old); @@ -947,8 +1348,11 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { if (OldType != New->getUnderlyingType() && Context.getCanonicalType(OldType) != Context.getCanonicalType(New->getUnderlyingType())) { + int Kind = 0; + if (isa<TypeAliasDecl>(Old)) + Kind = 1; Diag(New->getLocation(), diag::err_redefinition_different_typedef) - << New->getUnderlyingType() << OldType; + << Kind << New->getUnderlyingType() << OldType; if (Old->getLocation().isValid()) Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -958,8 +1362,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // declaration was a typedef. // FIXME: this is a potential source of wierdness if the type // spellings don't match exactly. - if (isa<TypedefDecl>(Old)) - New->setPreviousDeclaration(cast<TypedefDecl>(Old)); + if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) + New->setPreviousDeclaration(Typedef); if (getLangOptions().Microsoft) return; @@ -993,7 +1397,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // }; // // since that was the intent of DR56. - if (!isa<TypedefDecl >(Old)) + if (!isa<TypedefNameDecl>(Old)) return; Diag(New->getLocation(), diag::err_redefinition) @@ -1033,23 +1437,58 @@ DeclHasAttr(const Decl *D, const Attr *A) { return false; } -/// MergeDeclAttributes - append attributes from the Old decl to the New one. -static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) { - if (!Old->hasAttrs()) +/// mergeDeclAttributes - Copy attributes from the Old decl to the New one. +static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl, + ASTContext &C) { + if (!oldDecl->hasAttrs()) return; + + bool foundAny = newDecl->hasAttrs(); + // Ensure that any moving of objects within the allocated map is done before // we process them. - if (!New->hasAttrs()) - New->setAttrs(AttrVec()); + if (!foundAny) newDecl->setAttrs(AttrVec()); + for (specific_attr_iterator<InheritableAttr> - i = Old->specific_attr_begin<InheritableAttr>(), - e = Old->specific_attr_end<InheritableAttr>(); i != e; ++i) { - if (!DeclHasAttr(New, *i)) { - InheritableAttr *NewAttr = cast<InheritableAttr>((*i)->clone(C)); - NewAttr->setInherited(true); - New->addAttr(NewAttr); + i = oldDecl->specific_attr_begin<InheritableAttr>(), + e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C)); + newAttr->setInherited(true); + newDecl->addAttr(newAttr); + foundAny = true; } } + + if (!foundAny) newDecl->dropAttrs(); +} + +/// mergeParamDeclAttributes - Copy attributes from the old parameter +/// to the new one. +static void mergeParamDeclAttributes(ParmVarDecl *newDecl, + const ParmVarDecl *oldDecl, + ASTContext &C) { + if (!oldDecl->hasAttrs()) + return; + + bool foundAny = newDecl->hasAttrs(); + + // Ensure that any moving of objects within the allocated map is + // done before we process them. + if (!foundAny) newDecl->setAttrs(AttrVec()); + + for (specific_attr_iterator<InheritableParamAttr> + i = oldDecl->specific_attr_begin<InheritableParamAttr>(), + e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast<InheritableParamAttr>((*i)->clone(C)); + newAttr->setInherited(true); + newDecl->addAttr(newAttr); + foundAny = true; + } + } + + if (!foundAny) newDecl->dropAttrs(); } namespace { @@ -1145,10 +1584,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { New->getStorageClass() == SC_Static && Old->getStorageClass() != SC_Static && !canRedefineFunction(Old, getLangOptions())) { - Diag(New->getLocation(), diag::err_static_non_static) - << New; - Diag(Old->getLocation(), PrevDiag); - return true; + if (getLangOptions().Microsoft) { + Diag(New->getLocation(), diag::warn_static_non_static) << New; + Diag(Old->getLocation(), PrevDiag); + } else { + Diag(New->getLocation(), diag::err_static_non_static) << New; + Diag(Old->getLocation(), PrevDiag); + return true; + } } // If a function is first declared with a calling convention, but is @@ -1191,8 +1634,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { } // Merge regparm attribute. - if (OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) { - if (NewTypeInfo.getRegParm()) { + if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() || + OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) { + if (NewTypeInfo.getHasRegParm()) { Diag(New->getLocation(), diag::err_regparm_mismatch) << NewType->getRegParmType() << OldType->getRegParmType(); @@ -1335,10 +1779,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { ParamEnd = OldProto->arg_type_end(); ParamType != ParamEnd; ++ParamType) { ParmVarDecl *Param = ParmVarDecl::Create(Context, New, + SourceLocation(), SourceLocation(), 0, *ParamType, /*TInfo=*/0, SC_None, SC_None, 0); + Param->setScopeInfo(0, Params.size()); Param->setImplicit(); Params.push_back(Param); } @@ -1450,7 +1896,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { /// \returns false bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { // Merge the attributes - MergeDeclAttributes(New, Old, Context); + mergeDeclAttributes(New, Old, Context); // Merge the storage class. if (Old->getStorageClass() != SC_Extern && @@ -1465,14 +1911,33 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { if (Old->isDeleted()) New->setDeleted(); + // Merge attributes from the parameters. These can mismatch with K&R + // declarations. + if (New->getNumParams() == Old->getNumParams()) + for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) + mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i), + Context); + if (getLangOptions().CPlusPlus) return MergeCXXFunctionDecl(New, Old); return false; } -/// MergeVarDecl - We parsed a variable 'New' which has the same name and scope -/// as a previous declaration 'Old'. Figure out how to merge their types, +void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, + const ObjCMethodDecl *oldMethod) { + // Merge the attributes. + mergeDeclAttributes(newMethod, oldMethod, Context); + + // Merge attributes from the parameters. + for (ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(), + ni = newMethod->param_begin(), ne = newMethod->param_end(); + ni != ne; ++ni, ++oi) + mergeParamDeclAttributes(*ni, *oi, Context); +} + +/// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and +/// scope as a previous declaration 'Old'. Figure out how to merge their types, /// emitting diagnostics as appropriate. /// /// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back @@ -1489,8 +1954,10 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { if (AT && !AT->isDeduced()) { // We don't know what the new type is until the initializer is attached. return; - } else if (Context.hasSameType(New->getType(), Old->getType())) - return; + } else if (Context.hasSameType(New->getType(), Old->getType())) { + // These could still be something that needs exception specs checked. + return MergeVarDeclExceptionSpecs(New, Old); + } // C++ [basic.link]p10: // [...] the types specified by all declarations referring to a given // object or function shall be identical, except that declarations for an @@ -1564,7 +2031,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setInvalidDecl(); } - MergeDeclAttributes(New, Old, Context); + mergeDeclAttributes(New, Old, Context); // Merge the types. MergeVarDeclTypes(New, Old); @@ -1664,12 +2131,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, - DeclSpec &DS) { - // FIXME: Error on inline/virtual/explicit - // FIXME: Warn on useless __thread - // FIXME: Warn on useless const/volatile - // FIXME: Warn on useless static/extern/typedef/private_extern/mutable - // FIXME: Warn on useless attributes + DeclSpec &DS) { Decl *TagD = 0; TagDecl *Tag = 0; if (DS.getTypeSpecType() == DeclSpec::TST_class || @@ -1703,6 +2165,10 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return 0; return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0)); } + + // Track whether we warned about the fact that there aren't any + // declarators. + bool emittedWarning = false; if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) { ProcessDeclAttributeList(S, Record, DS.getAttributes().getList()); @@ -1715,6 +2181,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) << DS.getSourceRange(); + emittedWarning = true; } } @@ -1740,12 +2207,16 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DS.getStorageClassSpec() != DeclSpec::SCS_typedef) if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag)) if (Enum->enumerator_begin() == Enum->enumerator_end() && - !Enum->getIdentifier() && !Enum->isInvalidDecl()) + !Enum->getIdentifier() && !Enum->isInvalidDecl()) { Diag(Enum->getLocation(), diag::ext_no_declarators) << DS.getSourceRange(); + emittedWarning = true; + } + + // Skip all the checks below if we have a type error. + if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD; - if (!DS.isMissingDeclaratorOk() && - DS.getTypeSpecType() != DeclSpec::TST_error) { + if (!DS.isMissingDeclaratorOk()) { // Warn about typedefs of enums without names, since this is an // extension in both Microsoft and GNU. if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef && @@ -1757,7 +2228,40 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) << DS.getSourceRange(); - } + emittedWarning = true; + } + + // We're going to complain about a bunch of spurious specifiers; + // only do this if we're declaring a tag, because otherwise we + // should be getting diag::ext_no_declarators. + if (emittedWarning || (TagD && TagD->isInvalidDecl())) + return TagD; + + // Note that a linkage-specification sets a storage class, but + // 'extern "C" struct foo;' is actually valid and not theoretically + // useless. + if (DeclSpec::SCS scs = DS.getStorageClassSpec()) + if (!DS.isExternInLinkageSpec()) + Diag(DS.getStorageClassSpecLoc(), diag::warn_standalone_specifier) + << DeclSpec::getSpecifierName(scs); + + if (DS.isThreadSpecified()) + Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread"; + if (DS.getTypeQualifiers()) { + if (DS.getTypeQualifiers() & DeclSpec::TQ_const) + Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) + Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile"; + // Restrict is covered above. + } + if (DS.isInlineSpecified()) + Diag(DS.getInlineSpecLoc(), diag::warn_standalone_specifier) << "inline"; + if (DS.isVirtualSpecified()) + Diag(DS.getVirtualSpecLoc(), diag::warn_standalone_specifier) << "virtual"; + if (DS.isExplicitSpecified()) + Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit"; + + // FIXME: Warn on useless attributes return TagD; } @@ -2062,7 +2566,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // 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(), + Anon = FieldDecl::Create(Context, OwningClass, + DS.getSourceRange().getBegin(), + Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, @@ -2086,8 +2592,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, VarDecl::StorageClass SCAsWritten = StorageClassSpecToVarDeclStorageClass(SCSpec); - Anon = VarDecl::Create(Context, Owner, Record->getLocation(), - /*IdentifierInfo=*/0, + Anon = VarDecl::Create(Context, Owner, + DS.getSourceRange().getBegin(), + Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, SC, SCAsWritten); } @@ -2151,6 +2658,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, NamedDecl* Anon = FieldDecl::Create(Context, cast<RecordDecl>(CurContext), DS.getSourceRange().getBegin(), + DS.getSourceRange().getBegin(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, @@ -2379,6 +2887,26 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false); } +/// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: +/// If T is the name of a class, then each of the following shall have a +/// name different from T: +/// - every static data member of class T; +/// - every member function of class T +/// - every member of class T that is itself a type; +/// \returns true if the declaration name violates these rules. +bool Sema::DiagnoseClassNameShadow(DeclContext *DC, + DeclarationNameInfo NameInfo) { + DeclarationName Name = NameInfo.getName(); + + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) + if (Record->getIdentifier() && Record->getDeclName() == Name) { + Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name; + return true; + } + + return false; +} + Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition) { @@ -2466,23 +2994,12 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, D.setInvalidType(); } } - - // C++ [class.mem]p13: - // If T is the name of a class, then each of the following shall have a - // name different from T: - // - every static data member of class T; - // - every member function of class T - // - every member of class T that is itself a type; - if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) - if (Record->getIdentifier() && Record->getDeclName() == Name) { - Diag(D.getIdentifierLoc(), diag::err_member_name_of_class) - << Name; - - // If this is a typedef, we'll end up spewing multiple diagnostics. - // Just return early; it's safer. - if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) - return 0; - } + + if (DiagnoseClassNameShadow(DC, NameInfo)) + // If this is a typedef, we'll end up spewing multiple diagnostics. + // Just return early; it's safer. + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + return 0; NamedDecl *New; @@ -2777,6 +3294,15 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewTD, D); + return ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration); +} + +/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which +/// declares a typedef-name, either using the 'typedef' type specifier or via +/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'. +NamedDecl* +Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, + LookupResult &Previous, bool &Redeclaration) { // C99 6.7.7p2: If a typedef name specifies a variably modified type // then it shall have block scope. // Note that variably modified types must be fixed before merging the decl so @@ -2792,18 +3318,17 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, Oversized); if (!FixedTy.isNull()) { - Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size); + Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size); NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy)); } else { if (SizeIsNegative) - Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size); + Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size); else if (T->isVariableArrayType()) - Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope); + Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope); else if (Oversized.getBoolValue()) - Diag(D.getIdentifierLoc(), diag::err_array_too_large) - << Oversized.toString(10); + Diag(NewTD->getLocation(), diag::err_array_too_large) << Oversized.toString(10); else - Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope); + Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope); NewTD->setInvalidDecl(); } } @@ -2811,10 +3336,11 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Merge the decl with the existing one if appropriate. If the decl is // in an outer scope, it isn't the same thing. - FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false); + FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false, + /*ExplicitInstantiationOrSpecialization=*/false); if (!Previous.empty()) { Redeclaration = true; - MergeTypeDefDecl(NewTD, Previous); + MergeTypedefNameDecl(NewTD, Previous); } // If this is the C FILE type, notify the AST context. @@ -2952,8 +3478,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool isExplicitSpecialization = false; VarDecl *NewVD; if (!getLangOptions().CPlusPlus) { - NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), - II, R, TInfo, SC, SCAsWritten); + NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + R, TInfo, SC, SCAsWritten); if (D.isInvalidType()) NewVD->setInvalidDecl(); @@ -2988,7 +3515,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TemplateParamLists.size(); bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( @@ -2999,9 +3525,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, /*never a friend*/ false, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; - if (TemplateParams->size() > 0) { // There is no such thing as a variable template. Diag(D.getIdentifierLoc(), diag::err_template_variable) @@ -3017,13 +3540,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, << II << SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc()); - isExplicitSpecialization = true; } } - NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), - II, R, TInfo, SC, SCAsWritten); + NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + R, TInfo, SC, SCAsWritten); // If this decl has an auto type in need of deduction, make a note of the // Decl so we can diagnose uses of it in its own initializer. @@ -3036,9 +3559,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, SetNestedNameSpecifier(NewVD, D); - if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { + if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) { NewVD->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParamLists.size(), TemplateParamLists.release()); } } @@ -3092,7 +3615,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Don't consider existing declarations that are in a different // scope and are out-of-semantic-context declarations (if the new // declaration has linkage). - FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage()); + FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage(), + isExplicitSpecialization); if (!getLangOptions().CPlusPlus) CheckVariableDeclaration(NewVD, Previous, Redeclaration); @@ -3169,10 +3693,11 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { return; // Don't diagnose declarations at file scope. - DeclContext *NewDC = D->getDeclContext(); - if (NewDC->isFileContext()) + if (D->hasGlobalStorage()) return; - + + DeclContext *NewDC = D->getDeclContext(); + // Only diagnose if we're shadowing an unambiguous field or variable. if (R.getResultKind() != LookupResult::Found) return; @@ -3189,17 +3714,6 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { if (VarDecl *shadowedVar = dyn_cast<VarDecl>(ShadowedDecl)) if (shadowedVar->isExternC()) { - // Don't warn for this case: - // - // @code - // extern int bob; - // void f() { - // extern int bob; - // } - // @endcode - if (D->isExternC()) - return; - // For shadowing external vars, make sure that we point to the global // declaration, not a locally scoped extern declaration. for (VarDecl::redecl_iterator @@ -3528,8 +4042,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, FunctionTemplateDecl *FunctionTemplate = 0; bool isExplicitSpecialization = false; bool isFunctionTemplateSpecialization = false; - unsigned NumMatchedTemplateParamLists = 0; - + if (!getLangOptions().CPlusPlus) { // Determine whether the function was written with a // prototype. This true when: @@ -3540,7 +4053,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType()); - NewFD = FunctionDecl::Create(Context, DC, + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), NameInfo, R, TInfo, SC, SCAsWritten, isInline, HasPrototype); if (D.isInvalidType()) @@ -3549,7 +4062,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Set the lexical context. NewFD->setLexicalDeclContext(CurContext); // Filter out previous declarations that don't match the scope. - FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage()); + FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(), + /*ExplicitInstantiationOrSpecialization=*/false); } else { isFriend = D.getDeclSpec().isFriendSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); @@ -3566,14 +4080,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, AbstractReturnType)) D.setInvalidType(); - - if (isFriend) { - // 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 (Name.getNameKind() == DeclarationName::CXXConstructorName) { // This is a C++ constructor declaration. assert(DC->isRecord() && @@ -3584,6 +4090,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Create the new declaration NewFD = CXXConstructorDecl::Create(Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false); @@ -3594,6 +4101,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewFD = CXXDestructorDecl::Create(Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, isInline, /*isImplicitlyDeclared=*/false); @@ -3603,8 +4111,9 @@ 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, TInfo, SC, SCAsWritten, isInline, + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), Name, R, TInfo, + SC, SCAsWritten, isInline, /*hasPrototype=*/true); D.setInvalidType(); } @@ -3617,8 +4126,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, CheckConversionDeclarator(D, R, SC); NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, - isInline, isExplicit); + isInline, isExplicit, + SourceLocation()); isVirtualOkay = true; } else if (DC->isRecord()) { @@ -3636,7 +4147,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } bool isStatic = SC == SC_Static; - + // [class.free]p1: // Any allocation function for a class T is a static member // (even if not explicitly declared static). @@ -3649,25 +4160,34 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Name.getCXXOverloadedOperator() == OO_Delete || Name.getCXXOverloadedOperator() == OO_Array_Delete) isStatic = true; - + // This is a C++ method declaration. NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, - isStatic, SCAsWritten, isInline); + isStatic, SCAsWritten, isInline, + SourceLocation()); isVirtualOkay = !isStatic; } else { // Determine whether the function was written with a // prototype. This true when: // - we're in C++ (where every function has a prototype), - NewFD = FunctionDecl::Create(Context, DC, + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), NameInfo, R, TInfo, SC, SCAsWritten, isInline, true/*HasPrototype*/); } + + if (isFriend && !isInline && IsFunctionDefinition) { + // C++ [class.friend]p5 + // A function can be defined in a friend declaration of a + // class . . . . Such a function is implicitly inline. + NewFD->setImplicitlyInline(); + } + SetNestedNameSpecifier(NewFD, D); isExplicitSpecialization = false; isFunctionTemplateSpecialization = false; - NumMatchedTemplateParamLists = TemplateParamLists.size(); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -3680,7 +4200,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // determine whether we have a template or a template specialization. bool Invalid = false; if (TemplateParameterList *TemplateParams - = MatchTemplateParametersToScopeSpecifier( + = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getSourceRange().getBegin(), D.getCXXScopeSpec(), TemplateParamLists.get(), @@ -3688,54 +4208,71 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isFriend, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; - - if (TemplateParams->size() > 0) { - // This is a function template - - // 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 { - // This is a function template specialization. - isFunctionTemplateSpecialization = true; - - // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". - if (isFriend && isFunctionTemplateSpecialization) { - // We want to remove the "template<>", found here. - SourceRange RemoveRange = TemplateParams->getSourceRange(); - - // If we remove the template<> and the name is not a - // template-id, we're actually silently creating a problem: - // the friend declaration will refer to an untemplated decl, - // and clearly the user wants a template specialization. So - // we need to insert '<>' after the name. - SourceLocation InsertLoc; - if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { - InsertLoc = D.getName().getSourceRange().getEnd(); - InsertLoc = PP.getLocForEndOfToken(InsertLoc); - } + if (TemplateParams->size() > 0) { + // This is a function template - Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend) - << Name << RemoveRange - << FixItHint::CreateRemoval(RemoveRange) - << FixItHint::CreateInsertion(InsertLoc, "<>"); - } - } + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + return 0; + + // A destructor cannot be a template. + if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + Diag(NewFD->getLocation(), diag::err_destructor_template); + return 0; } - if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { - NewFD->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, - TemplateParamLists.release()); + FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, + NewFD->getLocation(), + Name, TemplateParams, + NewFD); + FunctionTemplate->setLexicalDeclContext(CurContext); + NewFD->setDescribedFunctionTemplate(FunctionTemplate); + + // For source fidelity, store the other template param lists. + if (TemplateParamLists.size() > 1) { + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size() - 1, + TemplateParamLists.release()); + } + } else { + // This is a function template specialization. + isFunctionTemplateSpecialization = true; + // For source fidelity, store all the template param lists. + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); + + // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". + if (isFriend) { + // We want to remove the "template<>", found here. + SourceRange RemoveRange = TemplateParams->getSourceRange(); + + // If we remove the template<> and the name is not a + // template-id, we're actually silently creating a problem: + // the friend declaration will refer to an untemplated decl, + // and clearly the user wants a template specialization. So + // we need to insert '<>' after the name. + SourceLocation InsertLoc; + if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + InsertLoc = D.getName().getSourceRange().getEnd(); + InsertLoc = PP.getLocForEndOfToken(InsertLoc); + } + + Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend) + << Name << RemoveRange + << FixItHint::CreateRemoval(RemoveRange) + << FixItHint::CreateInsertion(InsertLoc, "<>"); + } + } + } + else { + // All template param lists were matched against the scope specifier: + // this is NOT (an explicit specialization of) a template. + if (TemplateParamLists.size() > 0) + // For source fidelity, store all the template param lists. + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); } if (Invalid) { @@ -3802,7 +4339,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } // Filter out previous declarations that don't match the scope. - FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage()); + FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(), + isExplicitSpecialization || + isFunctionTemplateSpecialization); if (isFriend) { // For now, claim that the objects have no previous declaration. @@ -3863,8 +4402,13 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // In C++, the empty parameter-type-list must be spelled "void"; a // typedef of void is not permitted. if (getLangOptions().CPlusPlus && - Param->getType().getUnqualifiedType() != Context.VoidTy) - Diag(Param->getLocation(), diag::err_param_typedef_of_void); + Param->getType().getUnqualifiedType() != Context.VoidTy) { + bool IsTypeAlias = false; + if (const TypedefType *TT = Param->getType()->getAs<TypedefType>()) + IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl()); + Diag(Param->getLocation(), diag::err_param_typedef_of_void) + << IsTypeAlias; + } } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) { for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param); @@ -3892,6 +4436,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, AE = FT->arg_type_end(); AI != AE; ++AI) { ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI); + Param->setScopeInfo(0, Params.size()); Params.push_back(Param); } } else { @@ -3977,9 +4522,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, Previous)) NewFD->setInvalidDecl(); } else if (isFunctionTemplateSpecialization) { - if (CheckFunctionTemplateSpecialization(NewFD, - (HasExplicitTemplateArgs ? &TemplateArgs : 0), - Previous)) + if (CurContext->isDependentContext() && CurContext->isRecord() + && !isFriend) { + Diag(NewFD->getLocation(), diag::err_function_specialization_in_class) + << NewFD->getDeclName(); + NewFD->setInvalidDecl(); + return 0; + } else if (CheckFunctionTemplateSpecialization(NewFD, + (HasExplicitTemplateArgs ? &TemplateArgs : 0), + Previous)) NewFD->setInvalidDecl(); } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD)) { if (CheckMemberSpecialization(NewFD, Previous)) @@ -4049,7 +4600,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // are situations where these conditions don't apply and we // can actually do this check immediately. if (isFriend && - (NumMatchedTemplateParamLists || + (TemplateParamLists.size() || D.getCXXScopeSpec().getScopeRep()->isDependent() || CurContext->isDependentContext())) { // ignore these @@ -4146,7 +4697,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, RegisterLocallyScopedExternCDecl(NewFD, Previous, S); // Set this FunctionDecl's range up to the right paren. - NewFD->setLocEnd(D.getSourceRange().getEnd()); + NewFD->setRangeEnd(D.getSourceRange().getEnd()); if (getLangOptions().CPlusPlus) { if (FunctionTemplate) { @@ -4420,8 +4971,7 @@ void Sema::CheckMain(FunctionDecl* FD) { // Darwin passes an undocumented fourth argument of type char**. If // other platforms start sprouting these, the logic below will start // getting shifty. - if (nparams == 4 && - Context.Target.getTriple().getOS() == llvm::Triple::Darwin) + if (nparams == 4 && Context.Target.getTriple().isOSDarwin()) HasExtraParameters = false; if (HasExtraParameters) { @@ -4493,6 +5043,46 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { return true; } +namespace { + // Visits an initialization expression to see if OrigDecl is evaluated in + // its own initialization and throws a warning if it does. + class SelfReferenceChecker + : public EvaluatedExprVisitor<SelfReferenceChecker> { + Sema &S; + Decl *OrigDecl; + + public: + typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited; + + SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context), + S(S), OrigDecl(OrigDecl) { } + + void VisitExpr(Expr *E) { + if (isa<ObjCMessageExpr>(*E)) return; + Inherited::VisitExpr(E); + } + + void VisitImplicitCastExpr(ImplicitCastExpr *E) { + CheckForSelfReference(E); + Inherited::VisitImplicitCastExpr(E); + } + + void CheckForSelfReference(ImplicitCastExpr *E) { + if (E->getCastKind() != CK_LValueToRValue) return; + Expr* SubExpr = E->getSubExpr()->IgnoreParenImpCasts(); + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr); + if (!DRE) return; + Decl* ReferenceDecl = DRE->getDecl(); + if (OrigDecl != ReferenceDecl) return; + LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName, + Sema::NotForRedeclaration); + S.Diag(SubExpr->getLocStart(), diag::warn_uninit_self_reference_in_init) + << Result.getLookupName() << OrigDecl->getLocation() + << SubExpr->getSourceRange(); + } + }; +} + /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. @@ -4503,6 +5093,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (RealDecl == 0 || RealDecl->isInvalidDecl()) return; + // Check for self-references within variable initializers. + if (VarDecl *vd = dyn_cast<VarDecl>(RealDecl)) { + // Variables declared within a function/method body are handled + // by a dataflow analysis. + if (!vd->hasLocalStorage() && !vd->isStaticLocal()) + SelfReferenceChecker(*this, RealDecl).VisitExpr(Init); + } + else { + SelfReferenceChecker(*this, RealDecl).VisitExpr(Init); + } + 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. @@ -4533,15 +5134,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { - QualType DeducedType; - if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) { + TypeSourceInfo *DeducedType = 0; + if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) << VDecl->getDeclName() << VDecl->getType() << Init->getType() << Init->getSourceRange(); + if (!DeducedType) { RealDecl->setInvalidDecl(); return; } - VDecl->setType(DeducedType); + VDecl->setTypeSourceInfo(DeducedType); + VDecl->setType(DeducedType->getType()); // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. @@ -4952,7 +5555,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, const RecordType *Record = Context.getBaseElementType(Type)->getAs<RecordType>(); - if (Record && getLangOptions().CPlusPlus && !getLangOptions().CPlusPlus0x && + if (Record && getLangOptions().CPlusPlus && cast<CXXRecordDecl>(Record->getDecl())->isPOD()) { // C++03 [dcl.init]p9: // If no initializer is specified for an object, and the @@ -4965,7 +5568,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, // any, have an indeterminate initial value); if the object // or any of its subobjects are of const-qualified type, the // program is ill-formed. - // FIXME: DPG thinks it is very fishy that C++0x disables this. } else { // Check for jumps past the implicit initializer. C++0x // clarifies that this applies to a "variable with automatic @@ -4990,6 +5592,47 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, } } +void Sema::ActOnCXXForRangeDecl(Decl *D) { + VarDecl *VD = dyn_cast<VarDecl>(D); + if (!VD) { + Diag(D->getLocation(), diag::err_for_range_decl_must_be_var); + D->setInvalidDecl(); + return; + } + + VD->setCXXForRangeDecl(true); + + // for-range-declaration cannot be given a storage class specifier. + int Error = -1; + switch (VD->getStorageClassAsWritten()) { + case SC_None: + break; + case SC_Extern: + Error = 0; + break; + case SC_Static: + Error = 1; + break; + case SC_PrivateExtern: + Error = 2; + break; + case SC_Auto: + Error = 3; + break; + case SC_Register: + Error = 4; + break; + } + // FIXME: constexpr isn't allowed here. + //if (DS.isConstexprSpecified()) + // Error = 5; + if (Error != -1) { + Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class) + << VD->getDeclName() << Error; + D->setInvalidDecl(); + } +} + void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (var->isInvalidDecl()) return; @@ -5058,7 +5701,7 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (Decl *D = Group[i]) Decls.push_back(D); - return BuildDeclaratorGroup(Decls.data(), Decls.size(), + return BuildDeclaratorGroup(Decls.data(), Decls.size(), DS.getTypeSpecType() == DeclSpec::TST_auto); } @@ -5195,12 +5838,18 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // the enclosing context. This prevents them from accidentally // looking like class members in C++. ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), - TInfo, parmDeclType, II, - D.getIdentifierLoc(), + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + parmDeclType, TInfo, StorageClass, StorageClassAsWritten); if (D.isInvalidType()) - New->setInvalidDecl(); + New->setInvalidDecl(); + + assert(S->isFunctionPrototypeScope()); + assert(S->getFunctionPrototypeDepth() >= 1); + New->setScopeInfo(S->getFunctionPrototypeDepth() - 1, + S->getNextFunctionPrototypeIndex()); // Add the parameter declaration into this scope. S->AddDecl(New); @@ -5220,7 +5869,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T) { - ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0, + /* FIXME: setting StartLoc == Loc. + Would it be worth to modify callers so as to provide proper source + location for the unnamed parameters, embedding the parameter's type? */ + ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0, T, Context.getTrivialTypeSourceInfo(T, Loc), SC_None, SC_None, 0); Param->setImplicit(); @@ -5272,14 +5924,13 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param, } } -ParmVarDecl *Sema::CheckParameter(DeclContext *DC, - TypeSourceInfo *TSInfo, QualType T, - IdentifierInfo *Name, - SourceLocation NameLoc, +ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, + SourceLocation NameLoc, IdentifierInfo *Name, + QualType T, TypeSourceInfo *TSInfo, VarDecl::StorageClass StorageClass, VarDecl::StorageClass StorageClassAsWritten) { - ParmVarDecl *New = ParmVarDecl::Create(Context, DC, NameLoc, Name, - adjustParameterType(T), TSInfo, + ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name, + adjustParameterType(T), TSInfo, StorageClass, StorageClassAsWritten, 0); @@ -5331,7 +5982,8 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, // Implicitly declare the argument as type 'int' for lack of a better // type. - DeclSpec DS; + AttributeFactory attrs; + DeclSpec DS(attrs); const char* PrevSpec; // unused unsigned DiagID; // unused DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc, @@ -5374,7 +6026,7 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { return false; // Don't warn about inline functions. - if (FD->isInlineSpecified()) + if (FD->isInlined()) return false; // Don't warn about function templates. @@ -5400,6 +6052,22 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { return MissingPrototype; } +void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) { + // Don't complain if we're in GNU89 mode and the previous definition + // was an extern inline function. + const FunctionDecl *Definition; + if (FD->hasBody(Definition) && + !canRedefineFunction(Definition, getLangOptions())) { + if (getLangOptions().GNUMode && Definition->isInlineSpecified() && + Definition->getStorageClass() == SC_Extern) + Diag(FD->getLocation(), diag::err_redefinition_extern_inline) + << FD->getDeclName() << getLangOptions().CPlusPlus; + else + Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); + Diag(Definition->getLocation(), diag::note_previous_definition); + } +} + Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // Clear the last template instantiation error context. LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation(); @@ -5417,19 +6085,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { PushFunctionScope(); // See if this is a redefinition. - // But don't complain if we're in GNU89 mode and the previous definition - // was an extern inline function. - const FunctionDecl *Definition; - if (FD->hasBody(Definition) && - !canRedefineFunction(Definition, getLangOptions())) { - if (getLangOptions().GNUMode && Definition->isInlineSpecified() && - Definition->getStorageClass() == SC_Extern) - Diag(FD->getLocation(), diag::err_redefinition_extern_inline) - << FD->getDeclName() << getLangOptions().CPlusPlus; - else - Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); - Diag(Definition->getLocation(), diag::note_previous_definition); - } + if (!FD->isLateTemplateParsed()) + CheckForFunctionRedefinition(FD); // Builtin functions cannot be defined. if (unsigned BuiltinID = FD->getBuiltinID()) { @@ -5481,7 +6138,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { DLLImportAttr *DA = FD->getAttr<DLLImportAttr>(); if (DA && (!FD->getAttr<DLLExportAttr>())) { // dllimport attribute cannot be directly applied to definition. - if (!DA->isInherited()) { + // Microsoft accepts dllimport for functions defined within class scope. + if (!DA->isInherited() && + !(LangOpts.Microsoft && FD->getLexicalDeclContext()->isRecord())) { Diag(FD->getLocation(), diag::err_attribute_can_be_applied_only_to_symbol_declaration) << "dllimport"; @@ -5615,7 +6274,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for // deletion in some later function. - if (PP.getDiagnostics().hasErrorOccurred()) + if (PP.getDiagnostics().hasErrorOccurred() || + PP.getDiagnostics().getSuppressAllDiagnostics()) ExprTemporaries.clear(); else if (!isa<FunctionTemplateDecl>(dcl)) { // Since the body is valid, issue any analysis-based warnings that are @@ -5666,17 +6326,18 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, // Set a Declarator for the implicit definition: int foo(); const char *Dummy; - DeclSpec DS; + AttributeFactory attrFactory; + DeclSpec DS(attrFactory); unsigned DiagID; bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID); (void)Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); Declarator D(DS, Declarator::BlockContext); - D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(), - false, false, SourceLocation(), 0, + D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0, 0, 0, true, SourceLocation(), - false, SourceLocation(), - false, 0,0,0, Loc, Loc, D), + EST_None, SourceLocation(), + 0, 0, 0, 0, Loc, Loc, D), + DS.getAttributes(), SourceLocation()); D.SetIdentifier(&II, Loc); @@ -5784,6 +6445,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, // Scope manipulation handled by caller. TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext, + D.getSourceRange().getBegin(), D.getIdentifierLoc(), D.getIdentifier(), TInfo); @@ -5810,7 +6472,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, // Do nothing if the tag is not anonymous or already has an // associated typedef (from an earlier typedef in this decl group). if (tagFromDeclSpec->getIdentifier()) break; - if (tagFromDeclSpec->getTypedefForAnonDecl()) break; + if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break; // A well-formed anonymous tag must always be a TUK_Definition. assert(tagFromDeclSpec->isThisDeclarationADefinition()); @@ -5820,7 +6482,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, break; // Otherwise, set this is the anon-decl typedef for the tag. - tagFromDeclSpec->setTypedefForAnonDecl(NewTD); + tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); break; } @@ -5897,36 +6559,33 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // FIXME: Check explicit specializations more carefully. bool isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); bool Invalid = false; // We only need to do this matching if we have template parameters // or a scope specifier, which also conveniently avoids this work // for non-C++ cases. - if (NumMatchedTemplateParamLists || + if (TemplateParameterLists.size() > 0 || (SS.isNotEmpty() && TUK != TUK_Reference)) { if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier(KWLoc, SS, TemplateParameterLists.get(), - TemplateParameterLists.size(), + TemplateParameterLists.size(), TUK == TUK_Friend, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; - if (TemplateParams->size() > 0) { // This is a declaration or definition of a class template (which may // be a member of another template). + if (Invalid) return 0; - + OwnedDecl = false; DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attr, - TemplateParams, - AS); - TemplateParameterLists.release(); + TemplateParams, AS, + TemplateParameterLists.size() - 1, + (TemplateParameterList**) TemplateParameterLists.release()); return Result.get(); } else { // The "template<>" header is extraneous. @@ -6164,7 +6823,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // okay according to the likely resolution of an open issue; // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 if (getLangOptions().CPlusPlus) { - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(PrevDecl)) { + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) { if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) { TagDecl *Tag = TT->getDecl(); if (Tag->getDeclName() == Name && @@ -6184,7 +6843,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // in the same scope (so that the definition/declaration completes or // rementions the tag), reuse the decl. if (TUK == TUK_Reference || TUK == TUK_Friend || - isDeclInScope(PrevDecl, SearchDC, S)) { + isDeclInScope(PrevDecl, SearchDC, S, isExplicitSpecialization)) { // 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)) { @@ -6322,30 +6981,34 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, !Previous.isForRedeclaration()) { unsigned Kind = 0; if (isa<TypedefDecl>(PrevDecl)) Kind = 1; - else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2; + else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2; + else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3; Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind; Diag(PrevDecl->getLocation(), diag::note_declared_at); Invalid = true; // Otherwise, only diagnose if the declaration is in scope. - } else if (!isDeclInScope(PrevDecl, SearchDC, S)) { + } else if (!isDeclInScope(PrevDecl, SearchDC, S, + isExplicitSpecialization)) { // do nothing // Diagnose implicit declarations introduced by elaborated types. } else if (TUK == TUK_Reference || TUK == TUK_Friend) { unsigned Kind = 0; if (isa<TypedefDecl>(PrevDecl)) Kind = 1; - else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2; + else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2; + else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3; Diag(NameLoc, diag::err_tag_reference_conflict) << Kind; Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; // Otherwise it's a declaration. Call out a particularly common // case here. - } else if (isa<TypedefDecl>(PrevDecl)) { + } else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(PrevDecl)) { + unsigned Kind = 0; + if (isa<TypeAliasDecl>(PrevDecl)) Kind = 1; Diag(NameLoc, diag::err_tag_definition_of_typedef) - << Name - << cast<TypedefDecl>(PrevDecl)->getUnderlyingType(); + << Name << Kind << TND->getUnderlyingType(); Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; @@ -6385,7 +7048,7 @@ CreateNewDecl: if (Kind == TTK_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, KWLoc, + New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, cast_or_null<EnumDecl>(PrevDecl), ScopedEnum, ScopedEnumUsesClassTag, !EnumUnderlying.isNull()); // If this is an undefined enum, warn. @@ -6431,13 +7094,13 @@ CreateNewDecl: // struct X { int A; } D; D should chain to X. if (getLangOptions().CPlusPlus) { // FIXME: Look for a way to use RecordDecl for simple structs. - New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, + New = CXXRecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, cast_or_null<CXXRecordDecl>(PrevDecl)); - + if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit())) StdBadAlloc = cast<CXXRecordDecl>(New); } else - New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, + New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, cast_or_null<RecordDecl>(PrevDecl)); } @@ -6445,9 +7108,9 @@ CreateNewDecl: if (SS.isNotEmpty()) { if (SS.isSet()) { New->setQualifierInfo(SS.getWithLocInContext(Context)); - if (NumMatchedTemplateParamLists > 0) { + if (TemplateParameterLists.size() > 0) { New->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParameterLists.size(), (TemplateParameterList**) TemplateParameterLists.release()); } } @@ -6466,6 +7129,8 @@ CreateNewDecl: // the #pragma tokens are effectively skipped over during the // parsing of the struct). AddAlignmentAttributesForRecord(RD); + + AddMsStructLayoutForRecord(RD); } // If this is a specialization of a member class (of a class template), @@ -6541,7 +7206,7 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { } void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, - ClassVirtSpecifiers &CVS, + SourceLocation FinalLoc, SourceLocation LBraceLoc) { AdjustDeclIfTemplate(TagD); CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD); @@ -6551,10 +7216,8 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, if (!Record->getIdentifier()) return; - if (CVS.isFinalSpecified()) - Record->addAttr(new (Context) FinalAttr(CVS.getFinalLoc(), Context)); - if (CVS.isExplicitSpecified()) - Record->addAttr(new (Context) ExplicitAttr(CVS.getExplicitLoc(), Context)); + if (FinalLoc.isValid()) + Record->addAttr(new (Context) FinalAttr(FinalLoc, Context)); // C++ [class]p2: // [...] The class-name is also inserted into the scope of the @@ -6562,10 +7225,9 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, // purposes of access checking, the injected-class-name is treated // as if it were a public member name. CXXRecordDecl *InjectedClassName - = CXXRecordDecl::Create(Context, Record->getTagKind(), - CurContext, Record->getLocation(), + = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext, + Record->getLocStart(), Record->getLocation(), Record->getIdentifier(), - Record->getTagKeywordLoc(), /*PrevDecl=*/0, /*DelayTypeCreation=*/true); Context.getTypeDeclType(InjectedClassName, Record); @@ -6852,7 +7514,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } } - FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, TInfo, + FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo, BitWidth, Mutable); if (InvalidDecl) NewFD->setInvalidDecl(); @@ -7152,8 +7814,8 @@ Decl *Sema::ActOnIvar(Scope *S, } // Construct the decl. - ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, - EnclosingContext, Loc, II, T, + ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, EnclosingContext, + DeclStart, Loc, II, T, TInfo, ac, (Expr *)BitfieldWidth); if (II) { @@ -7216,7 +7878,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, Expr * BW = IntegerLiteral::Create(Context, Zero, Context.CharTy, DeclLoc); Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl), - DeclLoc, 0, + DeclLoc, DeclLoc, 0, Context.CharTy, Context.CreateTypeSourceInfo(Context.CharTy), ObjCIvarDecl::Private, BW, @@ -7281,20 +7943,27 @@ void Sema::ActOnFields(Scope* S, continue; } else if (FDTy->isIncompleteArrayType() && Record && ((i == NumFields - 1 && !Record->isUnion()) || - (getLangOptions().Microsoft && + ((getLangOptions().Microsoft || getLangOptions().CPlusPlus) && (i == NumFields - 1 || Record->isUnion())))) { // Flexible array member. - // Microsoft is more permissive regarding flexible array. + // Microsoft and g++ is more permissive regarding flexible array. // It will accept flexible array in union and also // as the sole element of a struct/class. if (getLangOptions().Microsoft) { if (Record->isUnion()) - Diag(FD->getLocation(), diag::ext_flexible_array_union) + Diag(FD->getLocation(), diag::ext_flexible_array_union_ms) + << FD->getDeclName(); + else if (NumFields == 1) + Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_ms) + << FD->getDeclName() << Record->getTagKind(); + } else if (getLangOptions().CPlusPlus) { + if (Record->isUnion()) + Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu) << FD->getDeclName(); else if (NumFields == 1) - Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate) + Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_gnu) << FD->getDeclName() << Record->getTagKind(); - } else if (NumNamedMembers < 1) { + } else if (NumNamedMembers < 1) { Diag(FD->getLocation(), diag::err_flexible_array_empty_struct) << FD->getDeclName(); FD->setInvalidDecl(); @@ -7547,7 +8216,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { // Force the type of the expression to 'int'. - ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast); + Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take(); } } @@ -7560,12 +8229,12 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) { if (getLangOptions().Microsoft) { Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy; - ImpCastExprToType(Val, EltTy, CK_IntegralCast); + Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); } else Diag(IdLoc, diag::err_enumerator_too_large) << EltTy; } else - ImpCastExprToType(Val, EltTy, CK_IntegralCast); + Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); } else { // C++0x [dcl.enum]p5: @@ -7949,11 +8618,14 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, NumPositiveBits, NumNegativeBits); } -Decl *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr) { +Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, + SourceLocation StartLoc, + SourceLocation EndLoc) { StringLiteral *AsmString = cast<StringLiteral>(expr); FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext, - Loc, AsmString); + AsmString, StartLoc, + EndLoc); CurContext->addDecl(New); return New; } |