diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp | 1787 |
1 files changed, 1261 insertions, 526 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index 9d91a48..8d993ef 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -33,11 +33,13 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Sema/DelayedDiagnostic.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 "clang/Lex/ModuleLoader.h" #include "llvm/ADT/Triple.h" #include <algorithm> #include <cstring> @@ -69,7 +71,8 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS, bool isClassName, bool HasTrailingDot, ParsedType ObjectTypePtr, - bool WantNontrivialTypeSourceInfo) { + bool WantNontrivialTypeSourceInfo, + IdentifierInfo **CorrectedII) { // Determine where we will perform name lookup. DeclContext *LookupCtx = 0; if (ObjectTypePtr) { @@ -144,6 +147,51 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, switch (Result.getResultKind()) { case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: + if (CorrectedII) { + TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(), + Kind, S, SS, 0, false, + Sema::CTC_Type); + IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo(); + TemplateTy Template; + bool MemberOfUnknownSpecialization; + UnqualifiedId TemplateName; + TemplateName.setIdentifier(NewII, NameLoc); + NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier(); + CXXScopeSpec NewSS, *NewSSPtr = SS; + if (SS && NNS) { + NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc)); + NewSSPtr = &NewSS; + } + if (Correction && (NNS || NewII != &II) && + // Ignore a correction to a template type as the to-be-corrected + // identifier is not a template (typo correction for template names + // is handled elsewhere). + !(getLangOptions().CPlusPlus && NewSSPtr && + isTemplateName(S, *NewSSPtr, false, TemplateName, ParsedType(), + false, Template, MemberOfUnknownSpecialization))) { + ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr, + isClassName, HasTrailingDot, ObjectTypePtr, + WantNontrivialTypeSourceInfo); + if (Ty) { + std::string CorrectedStr(Correction.getAsString(getLangOptions())); + std::string CorrectedQuotedStr( + Correction.getQuoted(getLangOptions())); + Diag(NameLoc, diag::err_unknown_typename_suggest) + << Result.getLookupName() << CorrectedQuotedStr + << FixItHint::CreateReplacement(SourceRange(NameLoc), + CorrectedStr); + if (NamedDecl *FirstDecl = Correction.getCorrectionDecl()) + Diag(FirstDecl->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + + if (SS && NNS) + SS->MakeTrivial(Context, NNS, SourceRange(NameLoc)); + *CorrectedII = NewII; + return Ty; + } + } + } + // If typo correction failed or was not performed, fall through case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: Result.suppressDiagnostics(); @@ -269,7 +317,7 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { /// A<T>::TYPE a; // no typename required because A<T> is a base class. /// }; /// @endcode -bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS) { +bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) { if (CurContext->isRecord()) { const Type *Ty = SS->getScopeRep()->getAsType(); @@ -278,8 +326,9 @@ bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS) { BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType())) return true; + return S->isFunctionPrototypeScope(); } - return false; + return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope(); } bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, @@ -361,7 +410,7 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, << &II << DC << SS->getRange(); else if (isDependentScopeSpecifier(*SS)) { unsigned DiagID = diag::err_typename_missing; - if (getLangOptions().Microsoft && isMicrosoftMissingTypename(SS)) + if (getLangOptions().MicrosoftMode && isMicrosoftMissingTypename(SS, S)) DiagID = diag::warn_typename_missing; Diag(SS->getRange().getBegin(), DiagID) @@ -419,24 +468,6 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, 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; @@ -737,11 +768,6 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) { return DC; } - // ObjCMethodDecls are parsed (for some reason) outside the context - // of the class. - if (isa<ObjCMethodDecl>(DC)) - return DC->getLexicalParent()->getLexicalParent(); - return DC->getLexicalParent(); } @@ -804,6 +830,29 @@ void Sema::ExitDeclaratorContext(Scope *S) { // disappear. } + +void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) { + FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (FunctionTemplateDecl *TFD = dyn_cast_or_null<FunctionTemplateDecl>(D)) { + // We assume that the caller has already called + // ActOnReenterTemplateScope + FD = TFD->getTemplatedDecl(); + } + if (!FD) + return; + + PushDeclContext(S, FD); + for (unsigned P = 0, NumParams = FD->getNumParams(); P < NumParams; ++P) { + ParmVarDecl *Param = FD->getParamDecl(P); + // If the parameter has an identifier, then add it to the scope + if (Param->getIdentifier()) { + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } + } +} + + /// \brief Determine whether we allow overloading of the function /// PrevDecl with another declaration. /// @@ -843,7 +892,9 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { // Out-of-line definitions shouldn't be pushed into scope in C++. // Out-of-line variable and function definitions shouldn't even in C. if ((getLangOptions().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) && - D->isOutOfLine()) + D->isOutOfLine() && + !D->getDeclContext()->getRedeclContext()->Equals( + D->getLexicalDeclContext()->getRedeclContext())) return; // Template instantiations should also not be pushed into scope. @@ -1086,12 +1137,28 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return true; } +static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx, + FixItHint &Hint) { + if (isa<LabelDecl>(D)) { + SourceLocation AfterColon = Lexer::findLocationAfterToken(D->getLocEnd(), + tok::colon, Ctx.getSourceManager(), Ctx.getLangOptions(), true); + if (AfterColon.isInvalid()) + return; + Hint = FixItHint::CreateRemoval(CharSourceRange:: + getCharRange(D->getLocStart(), AfterColon)); + } + return; +} + /// DiagnoseUnusedDecl - Emit warnings about declarations that are not used /// unless they are marked attr(unused). void Sema::DiagnoseUnusedDecl(const NamedDecl *D) { + FixItHint Hint; if (!ShouldDiagnoseUnusedDecl(D)) return; + GenerateFixForUnusedDecl(D, Context, Hint); + unsigned DiagID; if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable()) DiagID = diag::warn_unused_exception_param; @@ -1100,7 +1167,7 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D) { else DiagID = diag::warn_unused_variable; - Diag(D->getLocation(), DiagID) << D->getDeclName(); + Diag(D->getLocation(), DiagID) << D->getDeclName() << Hint; } static void CheckPoppedLabel(LabelDecl *L, Sema &S) { @@ -1246,7 +1313,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, << R; if (Context.BuiltinInfo.getHeaderName(BID) && Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl, Loc) - != Diagnostic::Ignored) + != DiagnosticsEngine::Ignored) Diag(Loc, diag::note_please_include_header) << Context.BuiltinInfo.getHeaderName(BID) << Context.BuiltinInfo.GetName(BID); @@ -1263,7 +1330,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, // Create Decl objects for each parameter, adding them to the // FunctionDecl. if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) { - llvm::SmallVector<ParmVarDecl*, 16> Params; + SmallVector<ParmVarDecl*, 16> Params; for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { ParmVarDecl *parm = ParmVarDecl::Create(Context, New, SourceLocation(), @@ -1273,7 +1340,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, parm->setScopeInfo(0, i); Params.push_back(parm); } - New->setParams(Params.data(), Params.size()); + New->setParams(Params); } AddKnownFunctionAttributes(New); @@ -1308,29 +1375,24 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { case 2: if (!TypeID->isStr("id")) break; - Context.ObjCIdRedefinitionType = New->getUnderlyingType(); + Context.setObjCIdRedefinitionType(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.ObjCClassRedefinitionType = New->getUnderlyingType(); + Context.setObjCClassRedefinitionType(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")) break; - Context.ObjCSelRedefinitionType = New->getUnderlyingType(); + Context.setObjCSelRedefinitionType(New->getUnderlyingType()); // Install the built-in type for 'SEL', ignoring the current definition. New->setTypeForDecl(Context.getObjCSelType().getTypePtr()); return; - case 8: - if (!TypeID->isStr("Protocol")) - break; - Context.setObjCProtoType(New->getUnderlyingType()); - return; } // Fall through - the typedef name was not a builtin type. } @@ -1382,7 +1444,13 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) New->setPreviousDeclaration(Typedef); - if (getLangOptions().Microsoft) + // __module_private__ is propagated to later declarations. + if (Old->isModulePrivate()) + New->setModulePrivate(); + else if (New->isModulePrivate()) + diagnoseModulePrivateRedeclaration(New, Old); + + if (getLangOptions().MicrosoftExt) return; if (getLangOptions().CPlusPlus) { @@ -1443,8 +1511,14 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { static bool DeclHasAttr(const Decl *D, const Attr *A) { const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A); + const AnnotateAttr *Ann = dyn_cast<AnnotateAttr>(A); for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i) if ((*i)->getKind() == A->getKind()) { + if (Ann) { + if (Ann->getAnnotation() == cast<AnnotateAttr>(*i)->getAnnotation()) + return true; + continue; + } // FIXME: Don't hardcode this check if (OA && isa<OwnershipAttr>(*i)) return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind(); @@ -1456,7 +1530,7 @@ DeclHasAttr(const Decl *D, const Attr *A) { /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl, - ASTContext &C) { + ASTContext &C, bool mergeDeprecation = true) { if (!oldDecl->hasAttrs()) return; @@ -1469,6 +1543,13 @@ static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl, for (specific_attr_iterator<InheritableAttr> i = oldDecl->specific_attr_begin<InheritableAttr>(), e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) { + // Ignore deprecated/unavailable/availability attributes if requested. + if (!mergeDeprecation && + (isa<DeprecatedAttr>(*i) || + isa<UnavailableAttr>(*i) || + isa<AvailabilityAttr>(*i))) + continue; + if (!DeclHasAttr(newDecl, *i)) { InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C)); newAttr->setInherited(true); @@ -1535,6 +1616,8 @@ Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) { return Sema::CXXDestructor; } else if (MD->isCopyAssignmentOperator()) { return Sema::CXXCopyAssignment; + } else if (MD->isMoveAssignmentOperator()) { + return Sema::CXXMoveAssignment; } return Sema::CXXInvalid; @@ -1605,7 +1688,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { New->getStorageClass() == SC_Static && Old->getStorageClass() != SC_Static && !canRedefineFunction(Old, getLangOptions())) { - if (getLangOptions().Microsoft) { + if (getLangOptions().MicrosoftExt) { Diag(New->getLocation(), diag::warn_static_non_static) << New; Diag(Old->getLocation(), PrevDiag); } else { @@ -1669,6 +1752,18 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { RequiresAdjustment = true; } + // Merge ns_returns_retained attribute. + if (OldTypeInfo.getProducesResult() != NewTypeInfo.getProducesResult()) { + if (NewTypeInfo.getProducesResult()) { + Diag(New->getLocation(), diag::err_returns_retained_mismatch); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + + NewTypeInfo = NewTypeInfo.withProducesResult(true); + RequiresAdjustment = true; + } + if (RequiresAdjustment) { NewType = Context.adjustFunctionType(NewType, NewTypeInfo); New->setType(QualType(NewType, 0)); @@ -1706,9 +1801,16 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // Preserve triviality. NewMethod->setTrivial(OldMethod->isTrivial()); + // MSVC allows explicit template specialization at class scope: + // 2 CXMethodDecls referring to the same function will be injected. + // We don't want a redeclartion error. + bool IsClassScopeExplicitSpecialization = + OldMethod->isFunctionTemplateSpecialization() && + NewMethod->isFunctionTemplateSpecialization(); bool isFriend = NewMethod->getFriendObjectKind(); - if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord()) { + if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord() && + !IsClassScopeExplicitSpecialization) { // -- 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. @@ -1790,7 +1892,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // The old declaration provided a function prototype, but the // new declaration does not. Merge in the prototype. assert(!OldProto->hasExceptionSpec() && "Exception spec in C"); - llvm::SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(), + SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(), OldProto->arg_type_end()); NewQType = Context.getFunctionType(NewFuncType->getResultType(), ParamTypes.data(), ParamTypes.size(), @@ -1799,7 +1901,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { New->setHasInheritedPrototype(); // Synthesize a parameter for each argument type. - llvm::SmallVector<ParmVarDecl*, 16> Params; + SmallVector<ParmVarDecl*, 16> Params; for (FunctionProtoType::arg_type_iterator ParamType = OldProto->arg_type_begin(), ParamEnd = OldProto->arg_type_end(); @@ -1815,7 +1917,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { Params.push_back(Param); } - New->setParams(Params.data(), Params.size()); + New->setParams(Params); } return MergeCompatibleFunctionDecls(New, Old); @@ -1836,8 +1938,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { Old->hasPrototype() && !New->hasPrototype() && New->getType()->getAs<FunctionProtoType>() && Old->getNumParams() == New->getNumParams()) { - llvm::SmallVector<QualType, 16> ArgTypes; - llvm::SmallVector<GNUCompatibleParamWarning, 16> Warnings; + SmallVector<QualType, 16> ArgTypes; + SmallVector<GNUCompatibleParamWarning, 16> Warnings; const FunctionProtoType *OldProto = Old->getType()->getAs<FunctionProtoType>(); const FunctionProtoType *NewProto @@ -1933,6 +2035,12 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { if (Old->isPure()) New->setPure(); + // __module_private__ is propagated to later declarations. + if (Old->isModulePrivate()) + New->setModulePrivate(); + else if (New->isModulePrivate()) + diagnoseModulePrivateRedeclaration(New, Old); + // Merge attributes from the parameters. These can mismatch with K&R // declarations. if (New->getNumParams() == Old->getNumParams()) @@ -1949,15 +2057,20 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, const ObjCMethodDecl *oldMethod) { + // We don't want to merge unavailable and deprecated attributes + // except from interface to implementation. + bool mergeDeprecation = isa<ObjCImplDecl>(newMethod->getDeclContext()); + // Merge the attributes. - mergeDeclAttributes(newMethod, oldMethod, Context); + mergeDeclAttributes(newMethod, oldMethod, Context, mergeDeprecation); // Merge attributes from the parameters. - for (ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(), + ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(); + for (ObjCMethodDecl::param_iterator ni = newMethod->param_begin(), ne = newMethod->param_end(); ni != ne; ++ni, ++oi) mergeParamDeclAttributes(*ni, *oi, Context); - + CheckObjCMethodOverride(newMethod, oldMethod, true); } @@ -2111,6 +2224,12 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { return New->setInvalidDecl(); } + // __module_private__ is propagated to later declarations. + if (Old->isModulePrivate()) + New->setModulePrivate(); + else if (New->isModulePrivate()) + diagnoseModulePrivateRedeclaration(New, Old); + // Variables with external linkage are analyzed in FinalizeDeclaratorGroup. // FIXME: The test for external storage here seems wrong? We still @@ -2193,6 +2312,9 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Tag = dyn_cast<TagDecl>(TagD); } + if (Tag) + Tag->setFreeStanding(); + if (unsigned TypeQuals = DS.getTypeQualifiers()) { // Enforce C99 6.7.3p2: "Types other than pointer types derived from object // or incomplete types shall not be restrict-qualified." @@ -2202,6 +2324,20 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, << DS.getSourceRange(); } + if (DS.isConstexprSpecified()) { + // C++0x [dcl.constexpr]p1: constexpr can only be applied to declarations + // and definitions of functions and variables. + if (Tag) + Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag) + << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 : + DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 : + DS.getTypeSpecType() == DeclSpec::TST_union ? 2 : 3); + else + Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators); + // Don't emit warnings after this error. + return TagD; + } + if (DS.isFriendSpecified()) { // If we're dealing with a decl but not a TagDecl, assume that // whatever routines created it handled the friendship aspect. @@ -2217,7 +2353,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) { ProcessDeclAttributeList(S, Record, DS.getAttributes().getList()); - if (!Record->getDeclName() && Record->isDefinition() && + if (!Record->getDeclName() && Record->isCompleteDefinition() && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { if (getLangOptions().CPlusPlus || Record->getDeclContext()->isRecord()) @@ -2230,7 +2366,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } // Check for Microsoft C extension: anonymous struct. - if (getLangOptions().Microsoft && !getLangOptions().CPlusPlus && + if (getLangOptions().MicrosoftExt && !getLangOptions().CPlusPlus && CurContext->isRecord() && DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) { // Handle 2 kinds of anonymous struct: @@ -2238,7 +2374,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, // and // STRUCT_TYPE; <- where STRUCT_TYPE is a typedef struct. RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag); - if ((Record && Record->getDeclName() && !Record->isDefinition()) || + if ((Record && Record->getDeclName() && !Record->isCompleteDefinition()) || (DS.getTypeSpecType() == DeclSpec::TST_typename && DS.getRepAsType().get()->isStructureType())) { Diag(DS.getSourceRange().getBegin(), diag::ext_ms_anonymous_struct) @@ -2305,6 +2441,12 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, if (DS.isExplicitSpecified()) Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit"; + if (DS.isModulePrivateSpecified() && + Tag && Tag->getDeclContext()->isFunctionOrMethod()) + Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class) + << Tag->getTagKind() + << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc()); + // FIXME: Warn on useless attributes return TagD; @@ -2379,7 +2521,7 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, DeclContext *Owner, RecordDecl *AnonRecord, AccessSpecifier AS, - llvm::SmallVector<NamedDecl*, 2> &Chaining, + SmallVector<NamedDecl*, 2> &Chaining, bool MSAnonStruct) { unsigned diagKind = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl @@ -2511,8 +2653,8 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Invalid = true; // Recover by adding 'static'. - DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(), - PrevSpec, DiagID, getLangOptions()); + DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(), + PrevSpec, DiagID); } // C++ [class.union]p3: // A storage class is not allowed in a declaration of an @@ -2524,8 +2666,8 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Invalid = true; // Recover by removing the storage specifier. - DS.SetStorageClassSpec(DeclSpec::SCS_unspecified, SourceLocation(), - PrevSpec, DiagID, getLangOptions()); + DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified, SourceLocation(), + PrevSpec, DiagID); } // Ignore const/volatile/restrict qualifiers. @@ -2582,7 +2724,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (!MemRecord->isAnonymousStructOrUnion() && MemRecord->getDeclName()) { // Visual C++ allows type definition in anonymous struct or union. - if (getLangOptions().Microsoft) + if (getLangOptions().MicrosoftExt) Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type) << (int)Record->isUnion(); else { @@ -2606,7 +2748,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, DK = diag::err_anonymous_record_with_static; // Visual C++ allows type definition in anonymous struct or union. - if (getLangOptions().Microsoft && + if (getLangOptions().MicrosoftExt && DK == diag::err_anonymous_record_with_type) Diag((*Mem)->getLocation(), diag::ext_anonymous_record_with_type) << (int)Record->isUnion(); @@ -2665,6 +2807,12 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, SC, SCAsWritten); + + // Default-initialize the implicit variable. This initialization will be + // trivial in almost all cases, except if a union member has an in-class + // initializer: + // union { int n = 0; }; + ActOnUninitializedDecl(Anon, /*TypeMayContainAuto=*/false); } Anon->setImplicit(); @@ -2676,7 +2824,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Inject the members of the anonymous struct/union into the owning // context and into the identifier resolver chain for name lookup // purposes. - llvm::SmallVector<NamedDecl*, 2> Chain; + SmallVector<NamedDecl*, 2> Chain; Chain.push_back(Anon); if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS, @@ -2740,7 +2888,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, // Inject the members of the anonymous struct into the current // context and into the identifier resolver chain for name lookup // purposes. - llvm::SmallVector<NamedDecl*, 2> Chain; + SmallVector<NamedDecl*, 2> Chain; Chain.push_back(Anon); if (InjectAnonymousStructOrUnionMembers(*this, S, CurContext, @@ -2855,26 +3003,51 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { } // switch (Name.getKind()) - assert(false && "Unknown name kind"); - return DeclarationNameInfo(); + llvm_unreachable("Unknown name kind"); +} + +static QualType getCoreType(QualType Ty) { + do { + if (Ty->isPointerType() || Ty->isReferenceType()) + Ty = Ty->getPointeeType(); + else if (Ty->isArrayType()) + Ty = Ty->castAsArrayTypeUnsafe()->getElementType(); + else + return Ty.withoutLocalFastQualifiers(); + } while (true); } -/// isNearlyMatchingFunction - Determine whether the C++ functions -/// Declaration and Definition are "nearly" matching. This heuristic -/// is used to improve diagnostics in the case where an out-of-line -/// function definition doesn't match any declaration within -/// the class or namespace. -static bool isNearlyMatchingFunction(ASTContext &Context, +/// hasSimilarParameters - Determine whether the C++ functions Declaration +/// and Definition have "nearly" matching parameters. This heuristic is +/// used to improve diagnostics in the case where an out-of-line function +/// definition doesn't match any declaration within the class or namespace. +/// Also sets Params to the list of indices to the parameters that differ +/// between the declaration and the definition. If hasSimilarParameters +/// returns true and Params is empty, then all of the parameters match. +static bool hasSimilarParameters(ASTContext &Context, FunctionDecl *Declaration, - FunctionDecl *Definition) { + FunctionDecl *Definition, + llvm::SmallVectorImpl<unsigned> &Params) { + Params.clear(); if (Declaration->param_size() != Definition->param_size()) return false; for (unsigned Idx = 0; Idx < Declaration->param_size(); ++Idx) { QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType(); QualType DefParamTy = Definition->getParamDecl(Idx)->getType(); - if (!Context.hasSameUnqualifiedType(DeclParamTy.getNonReferenceType(), - DefParamTy.getNonReferenceType())) + // The parameter types are identical + if (Context.hasSameType(DefParamTy, DeclParamTy)) + continue; + + QualType DeclParamBaseTy = getCoreType(DeclParamTy); + QualType DefParamBaseTy = getCoreType(DefParamTy); + const IdentifierInfo *DeclTyName = DeclParamBaseTy.getBaseTypeIdentifier(); + const IdentifierInfo *DefTyName = DefParamBaseTy.getBaseTypeIdentifier(); + + if (Context.hasSameUnqualifiedType(DeclParamBaseTy, DefParamBaseTy) || + (DeclTyName && DeclTyName == DefTyName)) + Params.push_back(Idx); + else // The two parameters aren't even close return false; } @@ -2900,7 +3073,8 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, case DeclSpec::TST_typename: case DeclSpec::TST_typeofType: case DeclSpec::TST_decltype: - case DeclSpec::TST_underlyingType: { + case DeclSpec::TST_underlyingType: + case DeclSpec::TST_atomic: { // Grab the type from the parser. TypeSourceInfo *TSI = 0; QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI); @@ -2955,8 +3129,8 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, } Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { - return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), - /*IsFunctionDefinition=*/false); + D.setFunctionDefinition(false); + return HandleDeclarator(S, D, MultiTemplateParamsArg(*this)); } /// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: @@ -2980,8 +3154,7 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC, } Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, - MultiTemplateParamsArg TemplateParamLists, - bool IsFunctionDefinition) { + MultiTemplateParamsArg TemplateParamLists) { // TODO: consider using NameInfo for diagnostic. DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); @@ -3180,22 +3353,21 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) Previous.clear(); - bool Redeclaration = false; + bool AddToScope = true; if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { if (TemplateParamLists.size()) { Diag(D.getIdentifierLoc(), diag::err_template_typedef); return 0; } - New = ActOnTypedefDeclarator(S, D, DC, R, TInfo, Previous, Redeclaration); + New = ActOnTypedefDeclarator(S, D, DC, TInfo, Previous); } else if (R->isFunctionType()) { - New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous, + New = ActOnFunctionDeclarator(S, D, DC, TInfo, Previous, move(TemplateParamLists), - IsFunctionDefinition, Redeclaration); + AddToScope); } else { - New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous, - move(TemplateParamLists), - Redeclaration); + New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, + move(TemplateParamLists)); } if (New == 0) @@ -3203,7 +3375,8 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, // If this has an identifier and is not an invalid redeclaration or // function template specialization, add it to the scope stack. - if (New->getDeclName() && !(Redeclaration && New->isInvalidDecl())) + if (New->getDeclName() && AddToScope && + !(D.isRedeclaration() && New->isInvalidDecl())) PushOnScopeChains(New, S); return New; @@ -3321,6 +3494,23 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, } } +llvm::DenseMap<DeclarationName, NamedDecl *>::iterator +Sema::findLocallyScopedExternalDecl(DeclarationName Name) { + if (ExternalSource) { + // Load locally-scoped external decls from the external source. + SmallVector<NamedDecl *, 4> Decls; + ExternalSource->ReadLocallyScopedExternalDecls(Decls); + for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos + = LocallyScopedExternalDecls.find(Decls[I]->getDeclName()); + if (Pos == LocallyScopedExternalDecls.end()) + LocallyScopedExternalDecls[Decls[I]->getDeclName()] = Decls[I]; + } + } + + return LocallyScopedExternalDecls.find(Name); +} + /// \brief Diagnose function specifiers on a declaration of an identifier that /// does not identify a function. void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { @@ -3341,8 +3531,7 @@ void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { NamedDecl* Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, TypeSourceInfo *TInfo, - LookupResult &Previous, bool &Redeclaration) { + TypeSourceInfo *TInfo, LookupResult &Previous) { // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1). if (D.getCXXScopeSpec().isSet()) { Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator) @@ -3362,6 +3551,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + if (D.getDeclSpec().isConstexprSpecified()) + Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) + << 1; if (D.getName().Kind != UnqualifiedId::IK_Identifier) { Diag(D.getName().StartLocation, diag::err_typedef_not_identifier) @@ -3369,7 +3561,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, return 0; } - TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, TInfo); + TypedefDecl *NewTD = ParseTypedefDecl(S, D, TInfo->getType(), TInfo); if (!NewTD) return 0; // Handle attributes prior to checking for duplicates in MergeVarDecl @@ -3377,7 +3569,10 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, CheckTypedefForVariablyModifiedType(S, NewTD); - return ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration); + bool Redeclaration = D.isRedeclaration(); + NamedDecl *ND = ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration); + D.setRedeclaration(Redeclaration); + return ND; } void @@ -3557,10 +3752,9 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) { NamedDecl* Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, - QualType R, TypeSourceInfo *TInfo, - LookupResult &Previous, - MultiTemplateParamsArg TemplateParamLists, - bool &Redeclaration) { + TypeSourceInfo *TInfo, LookupResult &Previous, + MultiTemplateParamsArg TemplateParamLists) { + QualType R = TInfo->getType(); DeclarationName Name = GetNameForDeclarator(D).getName(); // Check that there are no default arguments (C++ only). @@ -3585,7 +3779,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, IdentifierInfo *II = Name.getAsIdentifierInfo(); if (!II) { Diag(D.getIdentifierLoc(), diag::err_bad_variable_name) - << Name.getAsString(); + << Name; return 0; } @@ -3606,6 +3800,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + if (getLangOptions().OpenCL) { + // Set up the special work-group-local storage class for variables in the + // OpenCL __local address space. + if (R.getAddressSpace() == LangAS::opencl_local) + SC = SC_OpenCLWorkGroupLocal; + } + bool isExplicitSpecialization = false; VarDecl *NewVD; if (!getLangOptions().CPlusPlus) { @@ -3695,20 +3896,67 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, TemplateParamLists.size(), TemplateParamLists.release()); } + + if (D.getDeclSpec().isConstexprSpecified()) { + // FIXME: once we know whether there's an initializer, apply this to + // static data members too. + if (!NewVD->isStaticDataMember() && + !NewVD->isThisDeclarationADefinition()) { + // 'constexpr' is redundant and ill-formed on a non-defining declaration + // of a variable. Suggest replacing it with 'const' if appropriate. + SourceLocation ConstexprLoc = D.getDeclSpec().getConstexprSpecLoc(); + SourceRange ConstexprRange(ConstexprLoc, ConstexprLoc); + // If the declarator is complex, we need to move the keyword to the + // innermost chunk as we switch it from 'constexpr' to 'const'. + int Kind = DeclaratorChunk::Paren; + for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) { + Kind = D.getTypeObject(I).Kind; + if (Kind != DeclaratorChunk::Paren) + break; + } + if ((D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const) || + Kind == DeclaratorChunk::Reference) + Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl) + << FixItHint::CreateRemoval(ConstexprRange); + else if (Kind == DeclaratorChunk::Paren) + Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl) + << FixItHint::CreateReplacement(ConstexprRange, "const"); + else + Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl) + << FixItHint::CreateRemoval(ConstexprRange) + << FixItHint::CreateInsertion(D.getIdentifierLoc(), "const "); + } else { + NewVD->setConstexpr(true); + } + } } + // Set the lexical context. If the declarator has a C++ scope specifier, the + // lexical context will be different from the semantic context. + NewVD->setLexicalDeclContext(CurContext); + if (D.getDeclSpec().isThreadSpecified()) { if (NewVD->hasLocalStorage()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global); - else if (!Context.Target.isTLSSupported()) + else if (!Context.getTargetInfo().isTLSSupported()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_unsupported); else NewVD->setThreadSpecified(true); } - // Set the lexical context. If the declarator has a C++ scope specifier, the - // lexical context will be different from the semantic context. - NewVD->setLexicalDeclContext(CurContext); + if (D.getDeclSpec().isModulePrivateSpecified()) { + if (isExplicitSpecialization) + Diag(NewVD->getLocation(), diag::err_module_private_specialization) + << 2 + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + else if (NewVD->hasLocalStorage()) + Diag(NewVD->getLocation(), diag::err_module_private_local) + << 0 << NewVD->getDeclName() + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + else + NewVD->setModulePrivate(); + } // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewVD, D); @@ -3722,7 +3970,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (Expr *E = (Expr*)D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - llvm::StringRef Label = SE->getString(); + StringRef Label = SE->getString(); if (S->getFnParent() != 0) { switch (SC) { case SC_None: @@ -3730,12 +3978,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label; break; case SC_Register: - if (!Context.Target.isValidGCCRegisterName(Label)) + if (!Context.getTargetInfo().isValidGCCRegisterName(Label)) Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label; break; case SC_Static: case SC_Extern: case SC_PrivateExtern: + case SC_OpenCLWorkGroupLocal: break; } } @@ -3754,9 +4003,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, FilterLookupForScope(Previous, DC, S, NewVD->hasLinkage(), isExplicitSpecialization); - if (!getLangOptions().CPlusPlus) - CheckVariableDeclaration(NewVD, Previous, Redeclaration); - else { + if (!getLangOptions().CPlusPlus) { + D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); + } else { // Merge the decl with the existing one if appropriate. if (!Previous.empty()) { if (Previous.isSingleResult() && @@ -3777,7 +4026,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD->setInvalidDecl(); } - CheckVariableDeclaration(NewVD, Previous, Redeclaration); + D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); // This is an explicit specialization of a static data member. Check it. if (isExplicitSpecialization && !NewVD->isInvalidDecl() && @@ -3825,7 +4074,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { // Return if warning is ignored. if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, R.getNameLoc()) == - Diagnostic::Ignored) + DiagnosticsEngine::Ignored) return; // Don't diagnose declarations at file scope. @@ -3899,7 +4148,7 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { /// \brief Check -Wshadow without the advantage of a previous lookup. void Sema::CheckShadow(Scope *S, VarDecl *D) { if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, D->getLocation()) == - Diagnostic::Ignored) + DiagnosticsEngine::Ignored) return; LookupResult R(*this, D->getDeclName(), D->getLocation(), @@ -3918,18 +4167,21 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) { /// that have been instantiated from a template. /// /// Sets NewVD->isInvalidDecl() if an error was encountered. -void Sema::CheckVariableDeclaration(VarDecl *NewVD, - LookupResult &Previous, - bool &Redeclaration) { +/// +/// Returns true if the variable declaration is a redeclaration. +bool Sema::CheckVariableDeclaration(VarDecl *NewVD, + LookupResult &Previous) { // If the decl is already known invalid, don't check it. if (NewVD->isInvalidDecl()) - return; + return false; QualType T = NewVD->getType(); if (T->isObjCObjectType()) { - Diag(NewVD->getLocation(), diag::err_statically_allocated_object); - return NewVD->setInvalidDecl(); + Diag(NewVD->getLocation(), diag::err_statically_allocated_object) + << FixItHint::CreateInsertion(NewVD->getLocation(), "*"); + T = Context.getObjCObjectPointerType(T); + NewVD->setType(T); } // Emit an error if an address space was applied to decl with local storage. @@ -3938,12 +4190,13 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, // ISO/IEC TR 18037 S5.1.2 if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl); - return NewVD->setInvalidDecl(); + NewVD->setInvalidDecl(); + return false; } if (NewVD->hasLocalStorage() && T.isObjCGCWeak() && !NewVD->hasAttr<BlocksAttr>()) { - if (getLangOptions().getGCMode() != LangOptions::NonGC) + if (getLangOptions().getGC() != LangOptions::NonGC) Diag(NewVD->getLocation(), diag::warn_gc_attribute_weak_on_local); else Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); @@ -3977,7 +4230,8 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, else Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage) << SizeRange; - return NewVD->setInvalidDecl(); + NewVD->setInvalidDecl(); + return false; } if (FixedTy.isNull()) { @@ -3985,7 +4239,8 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope); else Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage); - return NewVD->setInvalidDecl(); + NewVD->setInvalidDecl(); + return false; } Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); @@ -3997,7 +4252,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, // an extern "C" variable, look for a non-visible extern "C" // declaration with the same name. llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = LocallyScopedExternalDecls.find(NewVD->getDeclName()); + = findLocallyScopedExternalDecl(NewVD->getDeclName()); if (Pos != LocallyScopedExternalDecls.end()) Previous.addDecl(Pos->second); } @@ -4005,17 +4260,20 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, if (T->isVoidType() && !NewVD->hasExternalStorage()) { Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type) << T; - return NewVD->setInvalidDecl(); + NewVD->setInvalidDecl(); + return false; } if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) { Diag(NewVD->getLocation(), diag::err_block_on_nonlocal); - return NewVD->setInvalidDecl(); + NewVD->setInvalidDecl(); + return false; } if (isVM && NewVD->hasAttr<BlocksAttr>()) { Diag(NewVD->getLocation(), diag::err_block_on_vm); - return NewVD->setInvalidDecl(); + NewVD->setInvalidDecl(); + return false; } // Function pointers and references cannot have qualified function type, only @@ -4032,13 +4290,15 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, Pointee->getAs<FunctionProtoType>()->getTypeQuals() != 0) { Diag(NewVD->getLocation(), diag::err_invalid_qualified_function_pointer) << PtrOrRef; - return NewVD->setInvalidDecl(); + NewVD->setInvalidDecl(); + return false; } if (!Previous.empty()) { - Redeclaration = true; MergeVarDecl(NewVD, Previous); + return true; } + return false; } /// \brief Data used with FindOverriddenMethod @@ -4108,233 +4368,397 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { return AddedAny; } -static void DiagnoseInvalidRedeclaration(Sema &S, FunctionDecl *NewFD) { - LookupResult Prev(S, NewFD->getDeclName(), NewFD->getLocation(), +namespace { + // Struct for holding all of the extra arguments needed by + // DiagnoseInvalidRedeclaration to call Sema::ActOnFunctionDeclarator. + struct ActOnFDArgs { + Scope *S; + Declarator &D; + MultiTemplateParamsArg TemplateParamLists; + bool AddToScope; + }; +} + +/// \brief Generate diagnostics for an invalid function redeclaration. +/// +/// This routine handles generating the diagnostic messages for an invalid +/// function redeclaration, including finding possible similar declarations +/// or performing typo correction if there are no previous declarations with +/// the same name. +/// +/// Returns a NamedDecl iff typo correction was performed and substituting in +/// the new declaration name does not cause new errors. +static NamedDecl* DiagnoseInvalidRedeclaration( + Sema &SemaRef, LookupResult &Previous, FunctionDecl *NewFD, + ActOnFDArgs &ExtraArgs) { + NamedDecl *Result = NULL; + DeclarationName Name = NewFD->getDeclName(); + DeclContext *NewDC = NewFD->getDeclContext(); + LookupResult Prev(SemaRef, Name, NewFD->getLocation(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); - S.LookupQualifiedName(Prev, NewFD->getDeclContext()); + llvm::SmallVector<unsigned, 1> MismatchedParams; + llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1> NearMatches; + TypoCorrection Correction; + bool isFriendDecl = (SemaRef.getLangOptions().CPlusPlus && + ExtraArgs.D.getDeclSpec().isFriendSpecified()); + unsigned DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend + : diag::err_member_def_does_not_match; + + NewFD->setInvalidDecl(); + SemaRef.LookupQualifiedName(Prev, NewDC); assert(!Prev.isAmbiguous() && "Cannot have an ambiguity in previous-declaration lookup"); - for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end(); - Func != FuncEnd; ++Func) { - if (isa<FunctionDecl>(*Func) && - isNearlyMatchingFunction(S.Context, cast<FunctionDecl>(*Func), NewFD)) - S.Diag((*Func)->getLocation(), diag::note_member_def_close_match); + if (!Prev.empty()) { + for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end(); + Func != FuncEnd; ++Func) { + FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func); + if (FD && + hasSimilarParameters(SemaRef.Context, FD, NewFD, MismatchedParams)) { + // Add 1 to the index so that 0 can mean the mismatch didn't + // involve a parameter + unsigned ParamNum = + MismatchedParams.empty() ? 0 : MismatchedParams.front() + 1; + NearMatches.push_back(std::make_pair(FD, ParamNum)); + } + } + // If the qualified name lookup yielded nothing, try typo correction + } else if ((Correction = SemaRef.CorrectTypo(Prev.getLookupNameInfo(), + Prev.getLookupKind(), 0, 0, NewDC)) && + Correction.getCorrection() != Name) { + // Trap errors. + Sema::SFINAETrap Trap(SemaRef); + + // Set up everything for the call to ActOnFunctionDeclarator + ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(), + ExtraArgs.D.getIdentifierLoc()); + Previous.clear(); + Previous.setLookupName(Correction.getCorrection()); + for (TypoCorrection::decl_iterator CDecl = Correction.begin(), + CDeclEnd = Correction.end(); + CDecl != CDeclEnd; ++CDecl) { + FunctionDecl *FD = dyn_cast<FunctionDecl>(*CDecl); + if (FD && hasSimilarParameters(SemaRef.Context, FD, NewFD, + MismatchedParams)) { + Previous.addDecl(FD); + } + } + bool wasRedeclaration = ExtraArgs.D.isRedeclaration(); + // TODO: Refactor ActOnFunctionDeclarator so that we can call only the + // pieces need to verify the typo-corrected C++ declaraction and hopefully + // eliminate the need for the parameter pack ExtraArgs. + Result = SemaRef.ActOnFunctionDeclarator(ExtraArgs.S, ExtraArgs.D, + NewFD->getDeclContext(), + NewFD->getTypeSourceInfo(), + Previous, + ExtraArgs.TemplateParamLists, + ExtraArgs.AddToScope); + if (Trap.hasErrorOccurred()) { + // Pretend the typo correction never occurred + ExtraArgs.D.SetIdentifier(Name.getAsIdentifierInfo(), + ExtraArgs.D.getIdentifierLoc()); + ExtraArgs.D.setRedeclaration(wasRedeclaration); + Previous.clear(); + Previous.setLookupName(Name); + Result = NULL; + } else { + for (LookupResult::iterator Func = Previous.begin(), + FuncEnd = Previous.end(); + Func != FuncEnd; ++Func) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func)) + NearMatches.push_back(std::make_pair(FD, 0)); + } + } + if (NearMatches.empty()) { + // Ignore the correction if it didn't yield any close FunctionDecl matches + Correction = TypoCorrection(); + } else { + DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend_suggest + : diag::err_member_def_does_not_match_suggest; + } } -} -NamedDecl* -Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, - QualType R, TypeSourceInfo *TInfo, - LookupResult &Previous, - MultiTemplateParamsArg TemplateParamLists, - bool IsFunctionDefinition, bool &Redeclaration) { - assert(R.getTypePtr()->isFunctionType()); + if (Correction) + SemaRef.Diag(NewFD->getLocation(), DiagMsg) + << Name << NewDC << Correction.getQuoted(SemaRef.getLangOptions()) + << FixItHint::CreateReplacement( + NewFD->getLocation(), + Correction.getAsString(SemaRef.getLangOptions())); + else + SemaRef.Diag(NewFD->getLocation(), DiagMsg) + << Name << NewDC << NewFD->getLocation(); + + bool NewFDisConst = false; + if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) + NewFDisConst = NewMD->getTypeQualifiers() & Qualifiers::Const; + + for (llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1>::iterator + NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end(); + NearMatch != NearMatchEnd; ++NearMatch) { + FunctionDecl *FD = NearMatch->first; + bool FDisConst = false; + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) + FDisConst = MD->getTypeQualifiers() & Qualifiers::Const; + + if (unsigned Idx = NearMatch->second) { + ParmVarDecl *FDParam = FD->getParamDecl(Idx-1); + SemaRef.Diag(FDParam->getTypeSpecStartLoc(), + diag::note_member_def_close_param_match) + << Idx << FDParam->getType() << NewFD->getParamDecl(Idx-1)->getType(); + } else if (Correction) { + SemaRef.Diag(FD->getLocation(), diag::note_previous_decl) + << Correction.getQuoted(SemaRef.getLangOptions()); + } else if (FDisConst != NewFDisConst) { + SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) + << NewFDisConst << FD->getSourceRange().getEnd(); + } else + SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_match); + } + return Result; +} - // TODO: consider using NameInfo for diagnostic. - DeclarationNameInfo NameInfo = GetNameForDeclarator(D); - DeclarationName Name = NameInfo.getName(); - FunctionDecl::StorageClass SC = SC_None; +static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef, Declarator &D) { switch (D.getDeclSpec().getStorageClassSpec()) { - default: assert(0 && "Unknown storage class!"); + default: llvm_unreachable("Unknown storage class!"); case DeclSpec::SCS_auto: case DeclSpec::SCS_register: case DeclSpec::SCS_mutable: - Diag(D.getDeclSpec().getStorageClassSpecLoc(), - diag::err_typecheck_sclass_func); + SemaRef.Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_typecheck_sclass_func); D.setInvalidType(); break; - case DeclSpec::SCS_unspecified: SC = SC_None; break; - case DeclSpec::SCS_extern: SC = SC_Extern; break; + case DeclSpec::SCS_unspecified: break; + case DeclSpec::SCS_extern: return SC_Extern; case DeclSpec::SCS_static: { - if (CurContext->getRedeclContext()->isFunctionOrMethod()) { + if (SemaRef.CurContext->getRedeclContext()->isFunctionOrMethod()) { // C99 6.7.1p5: // The declaration of an identifier for a function that has // block scope shall have no explicit storage-class specifier // other than extern // See also (C++ [dcl.stc]p4). - Diag(D.getDeclSpec().getStorageClassSpecLoc(), - diag::err_static_block_func); - SC = SC_None; + SemaRef.Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_static_block_func); + break; } else - SC = SC_Static; - break; + return SC_Static; } - case DeclSpec::SCS_private_extern: SC = SC_PrivateExtern; break; + case DeclSpec::SCS_private_extern: return SC_PrivateExtern; } - if (D.getDeclSpec().isThreadSpecified()) - Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + // No explicit storage class has already been returned + return SC_None; +} - // Do not allow returning a objc interface by-value. - if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) { - Diag(D.getIdentifierLoc(), - diag::err_object_cannot_be_passed_returned_by_value) << 0 - << R->getAs<FunctionType>()->getResultType(); - D.setInvalidType(); - } - - FunctionDecl *NewFD; +static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, + DeclContext *DC, QualType &R, + TypeSourceInfo *TInfo, + FunctionDecl::StorageClass SC, + bool &IsVirtualOkay) { + DeclarationNameInfo NameInfo = SemaRef.GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + + FunctionDecl *NewFD = 0; bool isInline = D.getDeclSpec().isInlineSpecified(); - bool isFriend = false; DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); FunctionDecl::StorageClass SCAsWritten = StorageClassSpecToFunctionDeclStorageClass(SCSpec); - FunctionTemplateDecl *FunctionTemplate = 0; - bool isExplicitSpecialization = false; - bool isFunctionTemplateSpecialization = false; - if (!getLangOptions().CPlusPlus) { + if (!SemaRef.getLangOptions().CPlusPlus) { // Determine whether the function was written with a // prototype. This true when: // - 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 = - (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || - (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType()); - - NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), + (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || + (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType()); + + NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getSourceRange().getBegin(), NameInfo, R, TInfo, SC, SCAsWritten, isInline, HasPrototype); if (D.isInvalidType()) NewFD->setInvalidDecl(); - + // Set the lexical context. - NewFD->setLexicalDeclContext(CurContext); - // Filter out previous declarations that don't match the scope. - FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(), - /*ExplicitInstantiationOrSpecialization=*/false); - } else { - isFriend = D.getDeclSpec().isFriendSpecified(); - bool isVirtual = D.getDeclSpec().isVirtualSpecified(); - bool isExplicit = D.getDeclSpec().isExplicitSpecified(); - bool isVirtualOkay = false; - - // 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. - if (!DC->isRecord() && - RequireNonAbstractType(D.getIdentifierLoc(), - R->getAs<FunctionType>()->getResultType(), - diag::err_abstract_type_in_decl, - AbstractReturnType)) - D.setInvalidType(); + NewFD->setLexicalDeclContext(SemaRef.CurContext); - if (Name.getNameKind() == DeclarationName::CXXConstructorName) { - // This is a C++ constructor declaration. - assert(DC->isRecord() && - "Constructors can only be declared in a member context"); - - R = CheckConstructorDeclarator(D, R, SC); - - // Create the new declaration - CXXConstructorDecl *NewCD = CXXConstructorDecl::Create( - Context, - cast<CXXRecordDecl>(DC), - D.getSourceRange().getBegin(), - NameInfo, R, TInfo, - isExplicit, isInline, - /*isImplicitlyDeclared=*/false); - - NewFD = NewCD; - } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { - // This is a C++ destructor declaration. - if (DC->isRecord()) { - R = CheckDestructorDeclarator(D, R, SC); - CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); - - CXXDestructorDecl *NewDD = CXXDestructorDecl::Create(Context, Record, - D.getSourceRange().getBegin(), - NameInfo, R, TInfo, - isInline, - /*isImplicitlyDeclared=*/false); - NewFD = NewDD; - isVirtualOkay = true; - - // If the class is complete, then we now create the implicit exception - // specification. If the class is incomplete or dependent, we can't do - // it yet. - if (getLangOptions().CPlusPlus0x && !Record->isDependentType() && - Record->getDefinition() && !Record->isBeingDefined() && - R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) { - AdjustDestructorExceptionSpec(Record, NewDD); - } + return NewFD; + } - } else { - Diag(D.getIdentifierLoc(), diag::err_destructor_not_member); - - // Create a FunctionDecl to satisfy the function definition parsing - // code path. - NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), - D.getIdentifierLoc(), Name, R, TInfo, - SC, SCAsWritten, isInline, - /*hasPrototype=*/true); - D.setInvalidType(); - } - } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { - if (!DC->isRecord()) { - Diag(D.getIdentifierLoc(), - diag::err_conv_function_not_member); - return 0; - } + bool isExplicit = D.getDeclSpec().isExplicitSpecified(); + bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); + + // 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. + if (!DC->isRecord() && + SemaRef.RequireNonAbstractType(D.getIdentifierLoc(), + R->getAs<FunctionType>()->getResultType(), + diag::err_abstract_type_in_decl, + SemaRef.AbstractReturnType)) + D.setInvalidType(); - CheckConversionDeclarator(D, R, SC); - NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC), + if (Name.getNameKind() == DeclarationName::CXXConstructorName) { + // This is a C++ constructor declaration. + assert(DC->isRecord() && + "Constructors can only be declared in a member context"); + + R = SemaRef.CheckConstructorDeclarator(D, R, SC); + return CXXConstructorDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, + R, TInfo, isExplicit, isInline, + /*isImplicitlyDeclared=*/false, + isConstexpr); + + } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + // This is a C++ destructor declaration. + if (DC->isRecord()) { + R = SemaRef.CheckDestructorDeclarator(D, R, SC); + CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); + CXXDestructorDecl *NewDD = CXXDestructorDecl::Create( + SemaRef.Context, Record, D.getSourceRange().getBegin(), - NameInfo, R, TInfo, - isInline, isExplicit, - SourceLocation()); - - 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 - // constructor if it has no return type). - // must have an invalid constructor that has a return type - if (Name.getAsIdentifierInfo() && - Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){ - Diag(D.getIdentifierLoc(), diag::err_constructor_return_type) - << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) - << SourceRange(D.getIdentifierLoc()); - return 0; + NameInfo, R, TInfo, isInline, + /*isImplicitlyDeclared=*/false); + + // If the class is complete, then we now create the implicit exception + // specification. If the class is incomplete or dependent, we can't do + // it yet. + if (SemaRef.getLangOptions().CPlusPlus0x && !Record->isDependentType() && + Record->getDefinition() && !Record->isBeingDefined() && + R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) { + SemaRef.AdjustDestructorExceptionSpec(Record, NewDD); } - 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). - if (Name.getCXXOverloadedOperator() == OO_New || - Name.getCXXOverloadedOperator() == OO_Array_New) - isStatic = true; - - // [class.free]p6 Any deallocation function for a class X is a static member - // (even if not explicitly declared static). - if (Name.getCXXOverloadedOperator() == OO_Delete || - Name.getCXXOverloadedOperator() == OO_Array_Delete) - isStatic = true; - - // This is a C++ method declaration. - CXXMethodDecl *NewMD = CXXMethodDecl::Create( - Context, cast<CXXRecordDecl>(DC), - D.getSourceRange().getBegin(), - NameInfo, R, TInfo, - isStatic, SCAsWritten, isInline, - SourceLocation()); - NewFD = NewMD; - - isVirtualOkay = !isStatic; + IsVirtualOkay = true; + return NewDD; + } 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, D.getSourceRange().getBegin(), - NameInfo, R, TInfo, SC, SCAsWritten, isInline, - true/*HasPrototype*/); + SemaRef.Diag(D.getIdentifierLoc(), diag::err_destructor_not_member); + D.setInvalidType(); + + // Create a FunctionDecl to satisfy the function definition parsing + // code path. + return FunctionDecl::Create(SemaRef.Context, DC, + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), Name, R, TInfo, + SC, SCAsWritten, isInline, + /*hasPrototype=*/true, isConstexpr); + } + + } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { + if (!DC->isRecord()) { + SemaRef.Diag(D.getIdentifierLoc(), + diag::err_conv_function_not_member); + return 0; + } + + SemaRef.CheckConversionDeclarator(D, R, SC); + IsVirtualOkay = true; + return CXXConversionDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, + R, TInfo, isInline, isExplicit, + isConstexpr, SourceLocation()); + + } else if (DC->isRecord()) { + // If the name 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 + // constructor if it has no return type). + if (Name.getAsIdentifierInfo() && + Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){ + SemaRef.Diag(D.getIdentifierLoc(), diag::err_constructor_return_type) + << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) + << SourceRange(D.getIdentifierLoc()); + return 0; + } + + 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). + if (Name.getCXXOverloadedOperator() == OO_New || + Name.getCXXOverloadedOperator() == OO_Array_New) + isStatic = true; + + // [class.free]p6 Any deallocation function for a class X is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_Delete || + Name.getCXXOverloadedOperator() == OO_Array_Delete) + isStatic = true; + + IsVirtualOkay = !isStatic; + + // This is a C++ method declaration. + return CXXMethodDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, R, + TInfo, isStatic, SCAsWritten, isInline, + isConstexpr, SourceLocation()); + + } else { + // Determine whether the function was written with a + // prototype. This true when: + // - we're in C++ (where every function has a prototype), + return FunctionDecl::Create(SemaRef.Context, DC, + D.getSourceRange().getBegin(), + NameInfo, R, TInfo, SC, SCAsWritten, isInline, + true/*HasPrototype*/, isConstexpr); + } +} + +NamedDecl* +Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, + TypeSourceInfo *TInfo, LookupResult &Previous, + MultiTemplateParamsArg TemplateParamLists, + bool &AddToScope) { + QualType R = TInfo->getType(); + + assert(R.getTypePtr()->isFunctionType()); + + // TODO: consider using NameInfo for diagnostic. + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + FunctionDecl::StorageClass SC = getFunctionStorageClass(*this, D); + + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + + // Do not allow returning a objc interface by-value. + if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) { + Diag(D.getIdentifierLoc(), + diag::err_object_cannot_be_passed_returned_by_value) << 0 + << R->getAs<FunctionType>()->getResultType() + << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*"); + + QualType T = R->getAs<FunctionType>()->getResultType(); + T = Context.getObjCObjectPointerType(T); + if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) { + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + R = Context.getFunctionType(T, FPT->arg_type_begin(), + FPT->getNumArgs(), EPI); } + else if (isa<FunctionNoProtoType>(R)) + R = Context.getFunctionNoProtoType(T); + } + + bool isFriend = false; + FunctionTemplateDecl *FunctionTemplate = 0; + bool isExplicitSpecialization = false; + bool isFunctionTemplateSpecialization = false; + bool isDependentClassScopeExplicitSpecialization = false; + bool isVirtualOkay = false; - if (isFriend && !isInline && IsFunctionDefinition) { + FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC, + isVirtualOkay); + if (!NewFD) return 0; + + if (getLangOptions().CPlusPlus) { + bool isInline = D.getDeclSpec().isInlineSpecified(); + bool isVirtual = D.getDeclSpec().isVirtualSpecified(); + bool isExplicit = D.getDeclSpec().isExplicitSpecified(); + bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); + isFriend = D.getDeclSpec().isFriendSpecified(); + if (isFriend && !isInline && D.isFunctionDefinition()) { // C++ [class.friend]p5 // A function can be defined in a friend declaration of a // class . . . . Such a function is implicitly inline. @@ -4377,6 +4801,16 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(NewFD->getLocation(), diag::err_destructor_template); return 0; } + + // If we're adding a template to a dependent context, we may need to + // rebuilding some of the types used within the template parameter list, + // now that we know what the current instantiation is. + if (DC->isDependentContext()) { + ContextRAII SavedContext(*this, DC); + if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) + Invalid = true; + } + FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, NewFD->getLocation(), @@ -4437,7 +4871,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (FunctionTemplate) FunctionTemplate->setInvalidDecl(); } - + // C++ [dcl.fct.spec]p5: // The virtual specifier shall only be used in declarations of // nonstatic class member functions that appear within a @@ -4474,7 +4908,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); } } - + // C++ [dcl.fct.spec]p6: // The explicit specifier shall be used only in the declaration of a // constructor or conversion function within its class definition; see 12.3.1 @@ -4495,10 +4929,32 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } - // Filter out previous declarations that don't match the scope. - FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(), - isExplicitSpecialization || - isFunctionTemplateSpecialization); + if (isConstexpr) { + // C++0x [dcl.constexpr]p2: constexpr functions and constexpr constructors + // are implicitly inline. + NewFD->setImplicitlyInline(); + + // C++0x [dcl.constexpr]p3: functions declared constexpr are required to + // be either constructors or to return a literal type. Therefore, + // destructors cannot be declared constexpr. + if (isa<CXXDestructorDecl>(NewFD)) + Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor); + } + + // If __module_private__ was specified, mark the function accordingly. + if (D.getDeclSpec().isModulePrivateSpecified()) { + if (isFunctionTemplateSpecialization) { + SourceLocation ModulePrivateLoc + = D.getDeclSpec().getModulePrivateSpecLoc(); + Diag(ModulePrivateLoc, diag::err_module_private_specialization) + << 0 + << FixItHint::CreateRemoval(ModulePrivateLoc); + } else { + NewFD->setModulePrivate(); + if (FunctionTemplate) + FunctionTemplate->setModulePrivate(); + } + } if (isFriend) { // For now, claim that the objects have no previous declaration. @@ -4510,7 +4966,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setAccess(AS_public); } - if (isa<CXXMethodDecl>(NewFD) && DC == CurContext && IsFunctionDefinition) { + if (isa<CXXMethodDecl>(NewFD) && DC == CurContext && + D.isFunctionDefinition()) { // A method is implicitly inline if it's defined in its class // definition. NewFD->setImplicitlyInline(); @@ -4530,6 +4987,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); } } + + // Filter out previous declarations that don't match the scope. + FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(), + isExplicitSpecialization || + isFunctionTemplateSpecialization); // Handle GNU asm-label extension (encoded as an attribute). if (Expr *E = (Expr*) D.getAsmLabel()) { @@ -4541,7 +5003,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Copy the parameter declarations from the declarator D to the function // declaration NewFD, if they are available. First scavenge them into Params. - llvm::SmallVector<ParmVarDecl*, 16> Params; + SmallVector<ParmVarDecl*, 16> Params; if (D.isFunctionDeclarator()) { DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); @@ -4603,8 +5065,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, assert(R->isFunctionNoProtoType() && NewFD->getNumParams() == 0 && "Should not need args for typedef of non-prototype fn"); } + // Finally, we know we have the right number of parameters, install them. - NewFD->setParams(Params.data(), Params.size()); + NewFD->setParams(Params); // Process the non-inheritable attributes on this declaration. ProcessDeclAttributes(S, NewFD, D, @@ -4613,9 +5076,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!getLangOptions().CPlusPlus) { // Perform semantic checking on the function declaration. bool isExplicitSpecialization=false; - CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, - Redeclaration); - assert((NewFD->isInvalidDecl() || !Redeclaration || + if (!NewFD->isInvalidDecl()) { + if (NewFD->getResultType()->isVariablyModifiedType()) { + // Functions returning a variably modified type violate C99 6.7.5.2p2 + // because all functions have linkage. + Diag(NewFD->getLocation(), diag::err_vm_func_decl); + NewFD->setInvalidDecl(); + } else { + if (NewFD->isMain()) + CheckMain(NewFD, D.getDeclSpec()); + D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, + isExplicitSpecialization)); + } + } + assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); } else { @@ -4676,8 +5150,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // that either the specialized function type or the specialized // template is dependent, and therefore matching will fail. In // this case, don't check the specialization yet. + bool InstantiationDependent = false; if (isFunctionTemplateSpecialization && isFriend && - (NewFD->getType()->isDependentType() || DC->isDependentContext())) { + (NewFD->getType()->isDependentType() || DC->isDependentContext() || + TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs.getArgumentArray(), TemplateArgs.size(), + InstantiationDependent))) { assert(HasExplicitTemplateArgs && "friend function specialization without template args"); if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs, @@ -4686,10 +5164,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } else if (isFunctionTemplateSpecialization) { if (CurContext->isDependentContext() && CurContext->isRecord() && !isFriend) { - Diag(NewFD->getLocation(), diag::err_function_specialization_in_class) + isDependentClassScopeExplicitSpecialization = true; + Diag(NewFD->getLocation(), getLangOptions().MicrosoftExt ? + diag::ext_function_specialization_in_class : + diag::err_function_specialization_in_class) << NewFD->getDeclName(); - NewFD->setInvalidDecl(); - return 0; } else if (CheckFunctionTemplateSpecialization(NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : 0), Previous)) @@ -4719,18 +5198,33 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // Perform semantic checking on the function declaration. - CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, - Redeclaration); + if (!isDependentClassScopeExplicitSpecialization) { + if (NewFD->isInvalidDecl()) { + // If this is a class member, mark the class invalid immediately. + // This avoids some consistency errors later. + if (CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(NewFD)) + methodDecl->getParent()->setInvalidDecl(); + } else { + if (NewFD->isMain()) + CheckMain(NewFD, D.getDeclSpec()); + D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, + isExplicitSpecialization)); + } + } - assert((NewFD->isInvalidDecl() || !Redeclaration || + assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); + if (NewFD->isConstexpr() && !NewFD->isInvalidDecl() && + !CheckConstexprFunctionDecl(NewFD, CCK_Declaration)) + NewFD->setInvalidDecl(); + NamedDecl *PrincipalDecl = (FunctionTemplate ? cast<NamedDecl>(FunctionTemplate) : NewFD); - if (isFriend && Redeclaration) { + if (isFriend && D.isRedeclaration()) { AccessSpecifier Access = AS_public; if (!NewFD->isInvalidDecl()) Access = NewFD->getPreviousDeclaration()->getAccess(); @@ -4752,7 +5246,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(), PrevTemplate? PrevTemplate->getTemplateParameters() : 0, D.getDeclSpec().isFriendSpecified() - ? (IsFunctionDefinition + ? (D.isFunctionDefinition() ? TPC_FriendFunctionTemplateDefinition : TPC_FriendFunctionTemplate) : (D.getCXXScopeSpec().isSet() && @@ -4764,7 +5258,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (NewFD->isInvalidDecl()) { // Ignore all the rest of this. - } else if (!Redeclaration) { + } else if (!D.isRedeclaration()) { + struct ActOnFDArgs ExtraArgs = { S, D, TemplateParamLists, + AddToScope }; // Fake up an access specifier if it's supposed to be a class member. if (isa<CXXRecordDecl>(NewFD->getDeclContext())) NewFD->setAccess(AS_public); @@ -4784,38 +5280,43 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, (TemplateParamLists.size() || D.getCXXScopeSpec().getScopeRep()->isDependent() || CurContext->isDependentContext())) { - // ignore these - } else { - // 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, - // C++ [namespace.memdef]p2). For example: - // - // class X { - // void f() const; - // }; - // - // void X::f() { } // ill-formed - // - // Complain about this problem, and attempt to suggest close - // matches (e.g., those that differ only in cv-qualifiers and - // whether the parameter types are references). - Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match) - << Name << DC << D.getCXXScopeSpec().getRange(); - NewFD->setInvalidDecl(); - - DiagnoseInvalidRedeclaration(*this, NewFD); - } + // ignore these + } else { + // 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, + // C++ [namespace.memdef]p2). For example: + // + // class X { + // void f() const; + // }; + // + // void X::f() { } // ill-formed + // + // Complain about this problem, and attempt to suggest close + // matches (e.g., those that differ only in cv-qualifiers and + // whether the parameter types are references). + + if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous, + NewFD, + ExtraArgs)) { + AddToScope = ExtraArgs.AddToScope; + return Result; + } + } // Unqualified local friend declarations are required to resolve // to something. - } else if (isFriend && cast<CXXRecordDecl>(CurContext)->isLocalClass()) { - Diag(D.getIdentifierLoc(), diag::err_no_matching_local_friend); - NewFD->setInvalidDecl(); - DiagnoseInvalidRedeclaration(*this, NewFD); + } else if (isFriend && cast<CXXRecordDecl>(CurContext)->isLocalClass()) { + if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous, + NewFD, + ExtraArgs)) { + AddToScope = ExtraArgs.AddToScope; + return Result; } + } - } else if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() && + } else if (!D.isFunctionDefinition() && D.getCXXScopeSpec().isSet() && !isFriend && !isFunctionTemplateSpecialization && !isExplicitSpecialization) { // An out-of-line member function declaration must also be a @@ -4839,7 +5340,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // attributes declared post-definition are currently ignored // FIXME: This should happen during attribute merging - if (Redeclaration && Previous.isSingleResult()) { + if (D.isRedeclaration() && Previous.isSingleResult()) { const FunctionDecl *Def; FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl()); if (PrevFD && PrevFD->isDefined(Def) && D.hasAttributes()) { @@ -4871,6 +5372,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (NewFD->getLinkage() == ExternalLinkage && !DC->isRecord()) AddPushedVisibilityAttribute(NewFD); + // If there's a #pragma clang arc_cf_code_audited in scope, consider + // marking the function. + AddCFAuditedAttribute(NewFD); + // If this is a locally-scoped extern C function, update the // map of such names. if (CurContext->isFunctionOrMethod() && NewFD->isExternC() @@ -4901,6 +5406,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Context.setcudaConfigureCallDecl(NewFD); } } + + // Here we have an function template explicit specialization at class scope. + // The actually specialization will be postponed to template instatiation + // time via the ClassScopeFunctionSpecializationDecl node. + if (isDependentClassScopeExplicitSpecialization) { + ClassScopeFunctionSpecializationDecl *NewSpec = + ClassScopeFunctionSpecializationDecl::Create( + Context, CurContext, SourceLocation(), + cast<CXXMethodDecl>(NewFD)); + CurContext->addDecl(NewSpec); + AddToScope = false; + } return NewFD; } @@ -4919,29 +5436,13 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, /// an explicit specialization of the previous declaration. /// /// This sets NewFD->isInvalidDecl() to true if there was an error. -void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, +/// +/// Returns true if the function declaration is a redeclaration. +bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, LookupResult &Previous, - bool IsExplicitSpecialization, - bool &Redeclaration) { - // If NewFD is already known erroneous, don't do any of this checking. - if (NewFD->isInvalidDecl()) { - // If this is a class member, mark the class invalid immediately. - // This avoids some consistency errors later. - if (isa<CXXMethodDecl>(NewFD)) - cast<CXXMethodDecl>(NewFD)->getParent()->setInvalidDecl(); - - return; - } - - if (NewFD->getResultType()->isVariablyModifiedType()) { - // Functions returning a variably modified type violate C99 6.7.5.2p2 - // because all functions have linkage. - Diag(NewFD->getLocation(), diag::err_vm_func_decl); - return NewFD->setInvalidDecl(); - } - - if (NewFD->isMain()) - CheckMain(NewFD); + bool IsExplicitSpecialization) { + assert(!NewFD->getResultType()->isVariablyModifiedType() + && "Variably modified return types are not handled here"); // Check for a previous declaration of this name. if (Previous.empty() && NewFD->isExternC()) { @@ -4949,11 +5450,13 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // an extern "C" function, look for a non-visible extern "C" // declaration with the same name. llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = LocallyScopedExternalDecls.find(NewFD->getDeclName()); + = findLocallyScopedExternalDecl(NewFD->getDeclName()); if (Pos != LocallyScopedExternalDecls.end()) Previous.addDecl(Pos->second); } + bool Redeclaration = false; + // Merge or overload the declaration with an existing declaration of // the same name, if appropriate. if (!Previous.empty()) { @@ -5003,8 +5506,10 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (Redeclaration) { // NewFD and OldDecl represent declarations that need to be // merged. - if (MergeFunctionDecl(NewFD, OldDecl)) - return NewFD->setInvalidDecl(); + if (MergeFunctionDecl(NewFD, OldDecl)) { + NewFD->setInvalidDecl(); + return Redeclaration; + } Previous.clear(); Previous.addDecl(OldDecl); @@ -5028,6 +5533,10 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, NewTemplateDecl->setMemberSpecialization(); assert(OldTemplateDecl->isMemberSpecialization()); } + + if (OldTemplateDecl->isModulePrivate()) + NewTemplateDecl->setModulePrivate(); + } else { if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions NewFD->setAccess(OldDecl->getAccess()); @@ -5054,7 +5563,8 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, Context.getCanonicalType(ClassType)); if (NewFD->getDeclName() != Name) { Diag(NewFD->getLocation(), diag::err_destructor_name); - return NewFD->setInvalidDecl(); + NewFD->setInvalidDecl(); + return Redeclaration; } } } else if (CXXConversionDecl *Conversion @@ -5086,13 +5596,17 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // Extra checking for C++ overloaded operators (C++ [over.oper]). if (NewFD->isOverloadedOperator() && - CheckOverloadedOperatorDeclaration(NewFD)) - return NewFD->setInvalidDecl(); + CheckOverloadedOperatorDeclaration(NewFD)) { + NewFD->setInvalidDecl(); + return Redeclaration; + } // Extra checking for C++0x literal operators (C++0x [over.literal]). if (NewFD->getLiteralIdentifier() && - CheckLiteralOperatorDeclaration(NewFD)) - return NewFD->setInvalidDecl(); + CheckLiteralOperatorDeclaration(NewFD)) { + NewFD->setInvalidDecl(); + return Redeclaration; + } // 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 @@ -5112,24 +5626,22 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } } } + return Redeclaration; } -void Sema::CheckMain(FunctionDecl* FD) { +void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { // 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->isInlineSpecified(); - bool isStatic = FD->getStorageClass() == SC_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; - } + if (FD->getStorageClass() == SC_Static) + Diag(DS.getStorageClassSpecLoc(), getLangOptions().CPlusPlus + ? diag::err_static_main : diag::warn_static_main) + << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); + if (FD->isInlineSpecified()) + Diag(DS.getInlineSpecLoc(), diag::err_inline_main) + << FixItHint::CreateRemoval(DS.getInlineSpecLoc()); QualType T = FD->getType(); assert(T->isFunctionType() && "function decl is not of function type"); @@ -5152,7 +5664,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().isOSDarwin()) + if (nparams == 4 && Context.getTargetInfo().getTriple().isOSDarwin()) HasExtraParameters = false; if (HasExtraParameters) { @@ -5231,41 +5743,89 @@ namespace { : public EvaluatedExprVisitor<SelfReferenceChecker> { Sema &S; Decl *OrigDecl; + bool isRecordType; + bool isPODType; public: typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited; SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context), - S(S), OrigDecl(OrigDecl) { } + S(S), OrigDecl(OrigDecl) { + isPODType = false; + isRecordType = false; + if (ValueDecl *VD = dyn_cast<ValueDecl>(OrigDecl)) { + isPODType = VD->getType().isPODType(S.Context); + isRecordType = VD->getType()->isRecordType(); + } + } void VisitExpr(Expr *E) { if (isa<ObjCMessageExpr>(*E)) return; + if (isRecordType) { + Expr *expr = E; + if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { + ValueDecl *VD = ME->getMemberDecl(); + if (isa<EnumConstantDecl>(VD) || isa<VarDecl>(VD)) return; + expr = ME->getBase(); + } + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(expr)) { + HandleDeclRefExpr(DRE); + return; + } + } Inherited::VisitExpr(E); } + void VisitMemberExpr(MemberExpr *E) { + if (E->getType()->canDecayToPointerType()) return; + if (isa<FieldDecl>(E->getMemberDecl())) + if (DeclRefExpr *DRE + = dyn_cast<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts())) { + HandleDeclRefExpr(DRE); + return; + } + Inherited::VisitMemberExpr(E); + } + void VisitImplicitCastExpr(ImplicitCastExpr *E) { - CheckForSelfReference(E); + if ((!isRecordType &&E->getCastKind() == CK_LValueToRValue) || + (isRecordType && E->getCastKind() == CK_NoOp)) { + Expr* SubExpr = E->getSubExpr()->IgnoreParenImpCasts(); + if (MemberExpr *ME = dyn_cast<MemberExpr>(SubExpr)) + SubExpr = ME->getBase()->IgnoreParenImpCasts(); + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr)) { + HandleDeclRefExpr(DRE); + return; + } + } 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(); + void VisitUnaryOperator(UnaryOperator *E) { + // For POD record types, addresses of its own members are well-defined. + if (isRecordType && isPODType) return; + Inherited::VisitUnaryOperator(E); + } + + void HandleDeclRefExpr(DeclRefExpr *DRE) { + Decl* ReferenceDecl = DRE->getDecl(); if (OrigDecl != ReferenceDecl) return; LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName, Sema::NotForRedeclaration); - S.DiagRuntimeBehavior(SubExpr->getLocStart(), SubExpr, + S.DiagRuntimeBehavior(DRE->getLocStart(), DRE, S.PDiag(diag::warn_uninit_self_reference_in_init) - << Result.getLookupName() + << Result.getLookupName() << OrigDecl->getLocation() - << SubExpr->getSourceRange()); + << DRE->getSourceRange()); } }; } +/// CheckSelfReference - Warns if OrigDecl is used in expression E. +void Sema::CheckSelfReference(Decl* OrigDecl, Expr *E) { + SelfReferenceChecker(*this, OrigDecl).VisitExpr(E); +} + /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. @@ -5281,10 +5841,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // Variables declared within a function/method body are handled // by a dataflow analysis. if (!vd->hasLocalStorage() && !vd->isStaticLocal()) - SelfReferenceChecker(*this, RealDecl).VisitExpr(Init); + CheckSelfReference(RealDecl, Init); } else { - SelfReferenceChecker(*this, RealDecl).VisitExpr(Init); + CheckSelfReference(RealDecl, Init); } if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) { @@ -5392,6 +5952,14 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } } + // OpenCL 1.1 6.5.2: "Variables allocated in the __local address space inside + // a kernel function cannot be initialized." + if (VDecl->getStorageClass() == SC_OpenCLWorkGroupLocal) { + Diag(VDecl->getLocation(), diag::err_local_cant_init); + VDecl->setInvalidDecl(); + return; + } + // Capture the variable that is being initialized and the style of // initialization. InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); @@ -5456,11 +6024,26 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // A member-declarator can contain a constant-initializer only // if it declares a static member (9.4) of const integral or // const enumeration type, see 9.4.2. + // + // C++0x [class.static.data]p3: + // If a non-volatile const static data member is of integral or + // enumeration type, its declaration in the class definition can + // specify a brace-or-equal-initializer in which every initalizer-clause + // that is an assignment-expression is a constant expression. A static + // data member of literal type can be declared in the class definition + // with the constexpr specifier; if so, its declaration shall specify a + // brace-or-equal-initializer in which every initializer-clause that is + // an assignment-expression is a constant expression. QualType T = VDecl->getType(); // Do nothing on dependent types. if (T->isDependentType()) { + // Allow any 'static constexpr' members, whether or not they are of literal + // type. We separately check that the initializer is a constant expression, + // which implicitly requires the member to be of literal type. + } else if (VDecl->isConstexpr()) { + // Require constness. } else if (!T.isConstQualified()) { Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const) @@ -5471,7 +6054,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } else if (T->isIntegralOrEnumerationType()) { // Check whether the expression is a constant expression. SourceLocation Loc; - if (Init->isValueDependent()) + if (getLangOptions().CPlusPlus0x && T.isVolatileQualified()) + // In C++0x, a non-constexpr const static data member with an + // in-class initializer cannot be volatile. + Diag(VDecl->getLocation(), diag::err_in_class_initializer_volatile); + else if (Init->isValueDependent()) ; // Nothing to check. else if (Init->isIntegerConstantExpr(Context, &Loc)) ; // Ok, it's an ICE! @@ -5488,31 +6075,33 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, VDecl->setInvalidDecl(); } - // We allow floating-point constants as an extension in C++03, and - // C++0x has far more complicated rules that we don't really - // implement fully. - } else { - bool Allowed = false; - if (getLangOptions().CPlusPlus0x) { - Allowed = T->isLiteralType(); - } else if (T->isFloatingType()) { // also permits complex, which is ok - Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type) - << T << Init->getSourceRange(); - Allowed = true; - } - - if (!Allowed) { - Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type) - << T << Init->getSourceRange(); - VDecl->setInvalidDecl(); - - // TODO: there are probably expressions that pass here that shouldn't. - } else if (!Init->isValueDependent() && - !Init->isConstantInitializer(Context, false)) { + // We allow floating-point constants as an extension. + } else if (T->isFloatingType()) { // also permits complex, which is ok + Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type) + << T << Init->getSourceRange(); + if (getLangOptions().CPlusPlus0x) + Diag(VDecl->getLocation(), + diag::note_in_class_initializer_float_type_constexpr) + << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); + + if (!Init->isValueDependent() && + !Init->isConstantInitializer(Context, false)) { Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant) << Init->getSourceRange(); VDecl->setInvalidDecl(); } + + // Suggest adding 'constexpr' in C++0x for literal types. + } else if (getLangOptions().CPlusPlus0x && T->isLiteralType()) { + Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type) + << T << Init->getSourceRange() + << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); + VDecl->setConstexpr(true); + + } else { + Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type) + << T << Init->getSourceRange(); + VDecl->setInvalidDecl(); } } else if (VDecl->isFileVarDecl()) { if (VDecl->getStorageClassAsWritten() == SC_Extern && @@ -5547,33 +6136,23 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, VDecl->setType(DclT); Init->setType(DclT); } - - - // If this variable is a local declaration with record type, make sure it - // doesn't have a flexible member initialization. We only support this as a - // global/static definition. - if (VDecl->hasLocalStorage()) - if (const RecordType *RT = VDecl->getType()->getAs<RecordType>()) - if (RT->getDecl()->hasFlexibleArrayMember()) { - // Check whether the initializer tries to initialize the flexible - // array member itself to anything other than an empty initializer list. - if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { - unsigned Index = std::distance(RT->getDecl()->field_begin(), - RT->getDecl()->field_end()) - 1; - if (Index < ILE->getNumInits() && - !(isa<InitListExpr>(ILE->getInit(Index)) && - cast<InitListExpr>(ILE->getInit(Index))->getNumInits() == 0)) { - Diag(VDecl->getLocation(), diag::err_nonstatic_flexible_variable); - VDecl->setInvalidDecl(); - } - } - } // Check any implicit conversions within the expression. CheckImplicitConversions(Init, VDecl->getLocation()); if (!VDecl->isInvalidDecl()) checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init); + + if (VDecl->isConstexpr() && !VDecl->isInvalidDecl() && + !VDecl->getType()->isDependentType() && + !Init->isTypeDependent() && !Init->isValueDependent() && + !Init->isConstantInitializer(Context, + VDecl->getType()->isReferenceType())) { + // FIXME: Improve this diagnostic to explain why the initializer is not + // a constant expression. + Diag(VDecl->getLocation(), diag::err_constexpr_var_requires_const_init) + << VDecl << Init->getSourceRange(); + } Init = MaybeCreateExprWithCleanups(Init); // Attach the initializer to the decl. @@ -5639,6 +6218,21 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, return; } + // C++0x [dcl.constexpr]p9: An object or reference declared constexpr must + // have an initializer. + // C++0x [class.static.data]p3: A static data member can be declared with + // the constexpr specifier; if so, its declaration shall specify + // a brace-or-equal-initializer. + // + // A static data member's definition may inherit an initializer from an + // in-class declaration. + if (Var->isConstexpr() && !Var->getAnyInitializer()) { + Diag(Var->getLocation(), diag::err_constexpr_var_requires_init) + << Var->getDeclName(); + Var->setInvalidDecl(); + return; + } + switch (Var->isThisDeclarationADefinition()) { case VarDecl::Definition: if (!Var->isStaticDataMember() || !Var->getAnyInitializer()) @@ -5829,10 +6423,11 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) { case SC_Register: Error = 4; break; + case SC_OpenCLWorkGroupLocal: + llvm_unreachable("Unexpected storage class"); } - // FIXME: constexpr isn't allowed here. - //if (DS.isConstexprSpecified()) - // Error = 5; + if (VD->isConstexpr()) + Error = 5; if (Error != -1) { Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class) << VD->getDeclName() << Error; @@ -5916,7 +6511,7 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, Decl **Group, unsigned NumDecls) { - llvm::SmallVector<Decl*, 8> Decls; + SmallVector<Decl*, 8> Decls; if (DS.isTypeSpecOwned()) Decls.push_back(DS.getRepAsDecl()); @@ -5996,6 +6591,9 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + if (D.getDeclSpec().isConstexprSpecified()) + Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) + << 0; DiagnoseFunctionSpecifiers(D); @@ -6074,6 +6672,12 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { ProcessDeclAttributes(S, New, D); + if (D.getDeclSpec().isModulePrivateSpecified()) + Diag(New->getLocation(), diag::err_module_private_local) + << 1 << New->getDeclName() + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + if (New->hasAttr<BlocksAttr>()) { Diag(New->getLocation(), diag::err_block_on_nonlocal); } @@ -6157,8 +6761,9 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, // - otherwise, it's an error if (T->isArrayType()) { if (!T.isConstQualified()) { - Diag(NameLoc, diag::err_arc_array_param_no_ownership) - << TSInfo->getTypeLoc().getSourceRange(); + DelayedDiagnostics.add( + sema::DelayedDiagnostic::makeForbiddenType( + NameLoc, diag::err_arc_array_param_no_ownership, T, false)); } lifetime = Qualifiers::OCL_ExplicitNone; } else { @@ -6185,8 +6790,10 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, // passed by reference. if (T->isObjCObjectType()) { Diag(NameLoc, - diag::err_object_cannot_be_passed_returned_by_value) << 1 << T; - New->setInvalidDecl(); + diag::err_object_cannot_be_passed_returned_by_value) << 1 << T + << FixItHint::CreateInsertion(NameLoc, "*"); + T = Context.getObjCObjectPointerType(T); + New->setType(T); } // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage @@ -6241,9 +6848,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, assert(D.isFunctionDeclarator() && "Not a function declarator!"); Scope *ParentScope = FnBodyScope->getParent(); + D.setFunctionDefinition(true); Decl *DP = HandleDeclarator(ParentScope, D, - MultiTemplateParamsArg(*this), - /*IsFunctionDefinition=*/true); + MultiTemplateParamsArg(*this)); return ActOnStartOfFunctionDef(FnBodyScope, DP); } @@ -6379,7 +6986,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // dllimport attribute cannot be directly applied to definition. // Microsoft accepts dllimport for functions defined within class scope. if (!DA->isInherited() && - !(LangOpts.Microsoft && FD->getLexicalDeclContext()->isRecord())) { + !(LangOpts.MicrosoftExt && FD->getLexicalDeclContext()->isRecord())) { Diag(FD->getLocation(), diag::err_attribute_can_be_applied_only_to_symbol_declaration) << "dllimport"; @@ -6389,7 +6996,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // Visual C++ appears to not think this is an issue, so only issue // a warning when Microsoft extensions are disabled. - if (!LangOpts.Microsoft) { + if (!LangOpts.MicrosoftExt) { // If a symbol previously declared dllimport is later defined, the // attribute is ignored in subsequent references, and a warning is // emitted. @@ -6417,7 +7024,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { /// FIXME: Employ a smarter algorithm that accounts for multiple return /// statements and the lifetimes of the NRVO candidates. We should be able to /// find a maximal set of NRVO variables. -static void ComputeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { +void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { ReturnStmt **Returns = Scope->Returns.data(); const VarDecl *NRVOCandidate = 0; @@ -6466,7 +7073,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // MSVC permits the use of pure specifier (=0) on function definition, // defined at class scope, warn about this non standard construct. - if (getLangOptions().Microsoft && FD->isPure()) + if (getLangOptions().MicrosoftExt && FD->isPure()) Diag(FD->getLocation(), diag::warn_pure_function_definition); if (!FD->isInvalidDecl()) { @@ -6478,7 +7085,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD)) MarkVTableUsed(FD->getLocation(), Constructor->getParent()); - ComputeNRVO(Body, getCurFunction()); + computeNRVO(Body, getCurFunction()); } assert(FD == getCurFunctionDecl() && "Function parsing confused"); @@ -6491,11 +7098,27 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, DiagnoseUnusedParameters(MD->param_begin(), MD->param_end()); DiagnoseSizeOfParametersAndReturnValue(MD->param_begin(), MD->param_end(), MD->getResultType(), MD); + + if (Body) + computeNRVO(Body, getCurFunction()); + } + if (ObjCShouldCallSuperDealloc) { + Diag(MD->getLocEnd(), diag::warn_objc_missing_super_dealloc); + ObjCShouldCallSuperDealloc = false; + } + if (ObjCShouldCallSuperFinalize) { + Diag(MD->getLocEnd(), diag::warn_objc_missing_super_finalize); + ObjCShouldCallSuperFinalize = false; } } else { return 0; } + assert(!ObjCShouldCallSuperDealloc && "This should only be set for " + "ObjC methods, which should have been handled in the block above."); + assert(!ObjCShouldCallSuperFinalize && "This should only be set for " + "ObjC methods, which should have been handled in the block above."); + // Verify and clean out per-function state. if (Body) { // C++ constructors that have function-try-blocks can't have return @@ -6504,8 +7127,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body)) DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body)); - // Verify that that gotos and switch cases don't jump into scopes illegally. - // Verify that that gotos and switch cases don't jump into scopes illegally. + // Verify that gotos and switch cases don't jump into scopes illegally. if (getCurFunction()->NeedsScopeChecking() && !dcl->isInvalidDecl() && !hasAnyUnrecoverableErrorsInThisFunction()) @@ -6532,6 +7154,10 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, ActivePolicy = &WP; } + if (FD && FD->isConstexpr() && !FD->isInvalidDecl() && + !CheckConstexprFunctionBody(FD, Body)) + FD->setInvalidDecl(); + assert(ExprTemporaries.empty() && "Leftover temporaries in function"); assert(!ExprNeedsCleanups && "Unaccounted cleanups in function"); } @@ -6552,6 +7178,15 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, return dcl; } + +/// When we finish delayed parsing of an attribute, we must attach it to the +/// relevant Decl. +void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D, + ParsedAttributes &Attrs) { + ProcessDeclAttributeList(S, D, Attrs.getList()); +} + + /// 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, @@ -6561,7 +7196,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, // this name as a function or variable. If so, use that // (non-visible) declaration, and complain about it. llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = LocallyScopedExternalDecls.find(&II); + = findLocallyScopedExternalDecl(&II); if (Pos != LocallyScopedExternalDecls.end()) { Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second; Diag(Pos->second->getLocation(), diag::note_previous_declaration); @@ -6651,6 +7286,9 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context)); } + if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) && + !FD->getAttr<ReturnsTwiceAttr>()) + FD->addAttr(::new (Context) ReturnsTwiceAttr(FD->getLocation(), Context)); if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->getAttr<NoThrowAttr>()) FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context)); if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->getAttr<ConstAttr>()) @@ -6712,6 +7350,16 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, return NewTD; } + if (D.getDeclSpec().isModulePrivateSpecified()) { + if (CurContext->isFunctionOrMethod()) + Diag(NewTD->getLocation(), diag::err_module_private_local) + << 2 << NewTD->getDeclName() + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + else + NewTD->setModulePrivate(); + } + // C++ [dcl.typedef]p8: // If the typedef declaration defines an unnamed class (or // enum), the first typedef-name declared by the declaration @@ -6853,6 +7501,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, AccessSpecifier AS, + SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, bool ScopedEnum, bool ScopedEnumUsesClassTag, @@ -6892,6 +7541,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attr, TemplateParams, AS, + ModulePrivateLoc, TemplateParameterLists.size() - 1, (TemplateParameterList**) TemplateParameterLists.release()); return Result.get(); @@ -6934,7 +7584,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, UPPC_FixedUnderlyingType)) EnumUnderlying = Context.IntTy.getTypePtr(); - } else if (getLangOptions().Microsoft) + } else if (getLangOptions().MicrosoftExt) // Microsoft enums are always of int type. EnumUnderlying = Context.IntTy.getTypePtr(); } @@ -7233,7 +7883,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // For our current ASTs this shouldn't be a problem, but will // need to be changed with DeclGroups. if ((TUK == TUK_Reference && (!PrevTagDecl->getFriendObjectKind() || - getLangOptions().Microsoft)) || TUK == TUK_Friend) + getLangOptions().MicrosoftExt)) || TUK == TUK_Friend) return PrevTagDecl; // Diagnose attempts to redefine a tag. @@ -7385,7 +8035,7 @@ CreateNewDecl: Diag(Def->getLocation(), diag::note_previous_definition); } else { unsigned DiagID = diag::ext_forward_ref_enum; - if (getLangOptions().Microsoft) + if (getLangOptions().MicrosoftExt) DiagID = diag::ext_ms_forward_ref_enum; else if (getLangOptions().CPlusPlus) DiagID = diag::err_forward_ref_enum; @@ -7454,6 +8104,23 @@ CreateNewDecl: AddMsStructLayoutForRecord(RD); } + if (PrevDecl && PrevDecl->isModulePrivate()) + New->setModulePrivate(); + else if (ModulePrivateLoc.isValid()) { + if (isExplicitSpecialization) + Diag(New->getLocation(), diag::err_module_private_specialization) + << 2 + << FixItHint::CreateRemoval(ModulePrivateLoc); + else if (PrevDecl && !PrevDecl->isModulePrivate()) + diagnoseModulePrivateRedeclaration(New, PrevDecl, ModulePrivateLoc); + // __module_private__ does not apply to local classes. However, we only + // diagnose this as an error when the declaration specifiers are + // freestanding. Here, we just ignore the __module_private__. + // foobar + else if (!SearchDC->isFunctionOrMethod()) + New->setModulePrivate(); + } + // If this is a specialization of a member class (of a class template), // check the specialization. if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous)) @@ -7480,7 +8147,7 @@ CreateNewDecl: // the tag name visible. if (TUK == TUK_Friend) New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() || - getLangOptions().Microsoft); + getLangOptions().MicrosoftExt); // Set the access specifier. if (!Invalid && SearchDC->isRecord()) @@ -7530,6 +8197,16 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { PushDeclContext(S, Tag); } +Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) { + assert(isa<ObjCContainerDecl>(IDecl) && + "ActOnObjCContainerStartDefinition - Not ObjCContainerDecl"); + DeclContext *OCD = cast<DeclContext>(IDecl); + assert(getContainingDC(OCD) == CurContext && + "The next DeclContext should be lexically contained in the current one."); + CurContext = OCD; + return IDecl; +} + void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, SourceLocation FinalLoc, SourceLocation LBraceLoc) { @@ -7581,6 +8258,21 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, Consumer.HandleTagDeclDefinition(Tag); } +void Sema::ActOnObjCContainerFinishDefinition() { + // Exit this scope of this interface definition. + PopDeclContext(); +} + +void Sema::ActOnObjCTemporaryExitContainerContext() { + OriginalLexicalContext = CurContext; + ActOnObjCContainerFinishDefinition(); +} + +void Sema::ActOnObjCReenterContainerContext() { + ActOnObjCContainerStartDefinition(cast<Decl>(OriginalLexicalContext)); + OriginalLexicalContext = 0; +} + void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast<TagDecl>(TagD); @@ -7669,7 +8361,7 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, /// ActOnField - Each field of a C struct/union is passed into this in order /// to create a FieldDecl object for it. Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, - Declarator &D, ExprTy *BitfieldWidth) { + Declarator &D, Expr *BitfieldWidth) { FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD), DeclStart, D, static_cast<Expr*>(BitfieldWidth), /*HasInit=*/false, AS_public); @@ -7703,6 +8395,9 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + if (D.getDeclSpec().isConstexprSpecified()) + Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) + << 2; // Check to see if this name was declared as a member previously LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); @@ -7735,6 +8430,9 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, if (NewFD->isInvalidDecl()) Record->setInvalidDecl(); + if (D.getDeclSpec().isModulePrivateSpecified()) + NewFD->setModulePrivate(); + if (NewFD->isInvalidDecl() && PrevDecl) { // Don't introduce NewFD into scope; there's already something // with the same name in the same scope. @@ -7968,8 +8666,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { } } - assert(0 && "found no user-declared constructors"); - return; + llvm_unreachable("found no user-declared constructors"); } break; @@ -8054,7 +8751,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { case CXXDestructor: hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break; default: - assert(0 && "unexpected special member"); return; + llvm_unreachable("unexpected special member"); } // Check for nontrivial bases (and recurse). @@ -8102,7 +8799,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { } } - assert(0 && "found no explanation for non-trivial member"); + llvm_unreachable("found no explanation for non-trivial member"); } /// TranslateIvarVisibility - Translate visibility from a token ID to an @@ -8110,7 +8807,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { static ObjCIvarDecl::AccessControl TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { switch (ivarVisibility) { - default: assert(0 && "Unknown visitibility kind"); + default: llvm_unreachable("Unknown visitibility kind"); case tok::objc_private: return ObjCIvarDecl::Private; case tok::objc_public: return ObjCIvarDecl::Public; case tok::objc_protected: return ObjCIvarDecl::Protected; @@ -8122,8 +8819,7 @@ TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { /// in order to create an IvarDecl object for it. Decl *Sema::ActOnIvar(Scope *S, SourceLocation DeclStart, - Decl *IntfDecl, - Declarator &D, ExprTy *BitfieldWidth, + Declarator &D, Expr *BitfieldWidth, tok::ObjCKeywordKind Visibility) { IdentifierInfo *II = D.getIdentifier(); @@ -8165,7 +8861,7 @@ Decl *Sema::ActOnIvar(Scope *S, Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) : ObjCIvarDecl::None; // Must set ivar's DeclContext to its enclosing interface. - ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(IntfDecl); + ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(CurContext); ObjCContainerDecl *EnclosingContext; if (ObjCImplementationDecl *IMPDecl = dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { @@ -8213,6 +8909,9 @@ Decl *Sema::ActOnIvar(Scope *S, if (getLangOptions().ObjCAutoRefCount && inferObjCARCLifetime(NewID)) NewID->setInvalidDecl(); + if (D.getDeclSpec().isModulePrivateSpecified()) + NewID->setModulePrivate(); + if (II) { // FIXME: When interfaces are DeclContexts, we'll need to add // these to the interface. @@ -8227,23 +8926,19 @@ Decl *Sema::ActOnIvar(Scope *S, /// class and class extensions. For every class @interface and class /// extension @interface, if the last ivar is a bitfield of any type, /// then add an implicit `char :0` ivar to the end of that interface. -void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, - llvm::SmallVectorImpl<Decl *> &AllIvarDecls) { +void Sema::ActOnLastBitfield(SourceLocation DeclLoc, + SmallVectorImpl<Decl *> &AllIvarDecls) { if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty()) return; Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl); - if (!Ivar->isBitField()) - return; - uint64_t BitFieldSize = - Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); - if (BitFieldSize == 0) + if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0) return; - ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl); + ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CurContext); if (!ID) { - if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) { + if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CurContext)) { if (!CD->IsClassExtension()) return; } @@ -8252,13 +8947,14 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, return; } // All conditions are met. Add a new bitfield to the tail end of ivars. - llvm::APInt Zero(Context.getTypeSize(Context.CharTy), 0); - Expr * BW = IntegerLiteral::Create(Context, Zero, Context.CharTy, DeclLoc); + llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0); + Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc); - Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl), + Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(CurContext), DeclLoc, DeclLoc, 0, Context.CharTy, - Context.CreateTypeSourceInfo(Context.CharTy), + Context.getTrivialTypeSourceInfo(Context.CharTy, + DeclLoc), ObjCIvarDecl::Private, BW, true); AllIvarDecls.push_back(Ivar); @@ -8266,27 +8962,25 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, void Sema::ActOnFields(Scope* S, SourceLocation RecLoc, Decl *EnclosingDecl, - Decl **Fields, unsigned NumFields, + llvm::ArrayRef<Decl *> Fields, SourceLocation LBrac, SourceLocation RBrac, AttributeList *Attr) { 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()) { - // FIXME: Deallocate fields? + if (EnclosingDecl->isInvalidDecl()) return; - } - // Verify that all the fields are okay. unsigned NumNamedMembers = 0; - llvm::SmallVector<FieldDecl*, 32> RecFields; + SmallVector<FieldDecl*, 32> RecFields; RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl); bool ARCErrReported = false; - for (unsigned i = 0; i != NumFields; ++i) { - FieldDecl *FD = cast<FieldDecl>(Fields[i]); + for (llvm::ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end(); + i != end; ++i) { + FieldDecl *FD = cast<FieldDecl>(*i); // Get the type for the field. const Type *FDTy = FD->getType().getTypePtr(); @@ -8321,25 +9015,26 @@ void Sema::ActOnFields(Scope* S, EnclosingDecl->setInvalidDecl(); continue; } else if (FDTy->isIncompleteArrayType() && Record && - ((i == NumFields - 1 && !Record->isUnion()) || - ((getLangOptions().Microsoft || getLangOptions().CPlusPlus) && - (i == NumFields - 1 || Record->isUnion())))) { + ((i + 1 == Fields.end() && !Record->isUnion()) || + ((getLangOptions().MicrosoftExt || + getLangOptions().CPlusPlus) && + (i + 1 == Fields.end() || Record->isUnion())))) { // Flexible array member. // 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 (getLangOptions().MicrosoftExt) { if (Record->isUnion()) Diag(FD->getLocation(), diag::ext_flexible_array_union_ms) << FD->getDeclName(); - else if (NumFields == 1) + else if (Fields.size() == 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) + else if (Fields.size() == 1) Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_gnu) << FD->getDeclName() << Record->getTagKind(); } else if (NumNamedMembers < 1) { @@ -8376,7 +9071,7 @@ void Sema::ActOnFields(Scope* S, // If this is a struct/class and this is not the last element, reject // it. Note that GCC supports variable sized arrays in the middle of // structures. - if (i != NumFields-1) + if (i + 1 != Fields.end()) Diag(FD->getLocation(), diag::ext_variable_sized_type_in_struct) << FD->getDeclName() << FD->getType(); else { @@ -8393,10 +9088,10 @@ void Sema::ActOnFields(Scope* S, Record->setHasObjectMember(true); } else if (FDTy->isObjCObjectType()) { /// A field cannot be an Objective-c object - Diag(FD->getLocation(), diag::err_statically_allocated_object); - FD->setInvalidDecl(); - EnclosingDecl->setInvalidDecl(); - continue; + Diag(FD->getLocation(), diag::err_statically_allocated_object) + << FixItHint::CreateInsertion(FD->getLocation(), "*"); + QualType T = Context.getObjCObjectPointerType(FD->getType()); + FD->setType(T); } else if (!getLangOptions().CPlusPlus) { if (getLangOptions().ObjCAutoRefCount && Record && !ARCErrReported) { @@ -8421,7 +9116,7 @@ void Sema::ActOnFields(Scope* S, } } else if (getLangOptions().ObjC1 && - getLangOptions().getGCMode() != LangOptions::NonGC && + getLangOptions().getGC() != LangOptions::NonGC && Record && !Record->hasObjectMember()) { if (FD->getType()->isObjCObjectPointerType() || FD->getType().isObjCGCStrong()) @@ -8650,7 +9345,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, SourceLocation IdLoc, IdentifierInfo *Id, Expr *Val) { - unsigned IntWidth = Context.Target.getIntWidth(); + unsigned IntWidth = Context.getTargetInfo().getIntWidth(); llvm::APSInt EnumVal(IntWidth); QualType EltTy; @@ -8691,7 +9386,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // ... if the initializing value of an enumerator cannot be // represented by the underlying type, the program is ill-formed. if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) { - if (getLangOptions().Microsoft) { + if (getLangOptions().MicrosoftExt) { Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy; Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); } else @@ -8806,7 +9501,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, AttributeList *Attr, - SourceLocation EqualLoc, ExprTy *val) { + SourceLocation EqualLoc, Expr *val) { EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl); EnumConstantDecl *LastEnumConst = cast_or_null<EnumConstantDecl>(lastEnumConst); @@ -8894,9 +9589,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // 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(); + unsigned IntWidth = Context.getTargetInfo().getIntWidth(); + unsigned CharWidth = Context.getTargetInfo().getCharWidth(); + unsigned ShortWidth = Context.getTargetInfo().getShortWidth(); // Verify that all the values are okay, compute the size of the values, and // reverse the list. @@ -8969,12 +9664,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, BestType = Context.IntTy; BestWidth = IntWidth; } else { - BestWidth = Context.Target.getLongWidth(); + BestWidth = Context.getTargetInfo().getLongWidth(); if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) { BestType = Context.LongTy; } else { - BestWidth = Context.Target.getLongLongWidth(); + BestWidth = Context.getTargetInfo().getLongLongWidth(); if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth) Diag(Enum->getLocation(), diag::warn_enum_too_large); @@ -9001,13 +9696,13 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) ? Context.UnsignedIntTy : Context.IntTy; } else if (NumPositiveBits <= - (BestWidth = Context.Target.getLongWidth())) { + (BestWidth = Context.getTargetInfo().getLongWidth())) { BestType = Context.UnsignedLongTy; BestPromotionType = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) ? Context.UnsignedLongTy : Context.LongTy; } else { - BestWidth = Context.Target.getLongLongWidth(); + BestWidth = Context.getTargetInfo().getLongLongWidth(); assert(NumPositiveBits <= BestWidth && "How could an initializer get larger than ULL?"); BestType = Context.UnsignedLongLongTy; @@ -9094,6 +9789,33 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, return New; } +DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc, + IdentifierInfo &ModuleName, + SourceLocation ModuleNameLoc) { + ModuleKey Module = PP.getModuleLoader().loadModule(ImportLoc, + ModuleName, ModuleNameLoc); + if (!Module) + return true; + + // FIXME: Actually create a declaration to describe the module import. + (void)Module; + return DeclResult((Decl *)0); +} + +void +Sema::diagnoseModulePrivateRedeclaration(NamedDecl *New, NamedDecl *Old, + SourceLocation ModulePrivateKeyword) { + assert(!Old->isModulePrivate() && "Old is module-private!"); + + Diag(New->getLocation(), diag::err_module_private_follows_public) + << New->getDeclName() << SourceRange(ModulePrivateKeyword); + Diag(Old->getLocation(), diag::note_previous_declaration) + << Old->getDeclName(); + + // Drop the __module_private__ from the new declaration, since it's invalid. + New->setModulePrivate(false); +} + void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, SourceLocation PragmaLoc, SourceLocation NameLoc) { @@ -9126,3 +9848,16 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, std::pair<IdentifierInfo*,WeakInfo>(AliasName, W)); } } + +Decl *Sema::getObjCDeclContext() const { + return (dyn_cast_or_null<ObjCContainerDecl>(CurContext)); +} + +AvailabilityResult Sema::getCurContextAvailability() const { + const Decl *D = cast<Decl>(getCurLexicalContext()); + // A category implicitly has the availability of the interface. + if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D)) + D = CatD->getClassInterface(); + + return D->getAvailability(); +} |