diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-08-21 03:04:33 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-08-21 03:04:33 +0000 |
commit | b9fa99649bc99e2be9d06511d16f266225eae860 (patch) | |
tree | c613a456b27dcd04d793d764d1b47310aff63d23 /clang/lib/Sema | |
parent | 772527c57b4b949905e39ec03360f6f9d19d2729 (diff) | |
download | bcm5719-llvm-b9fa99649bc99e2be9d06511d16f266225eae860.tar.gz bcm5719-llvm-b9fa99649bc99e2be9d06511d16f266225eae860.zip |
[modules] When we see a definition of a function for which we already have a
non-visible definition, skip the new definition to avoid ending up with a
function with multiple definitions.
llvm-svn: 245664
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 60 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 18 |
2 files changed, 41 insertions, 37 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a8d1e1203e4..63093b9fddd 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2272,9 +2272,17 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { const Attr *NewAttribute = NewAttributes[I]; if (isa<AliasAttr>(NewAttribute)) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New)) - S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def)); - else { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New)) { + Sema::SkipBodyInfo SkipBody; + S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def), &SkipBody); + + // If we're skipping this definition, drop the "alias" attribute. + if (SkipBody.ShouldSkip) { + NewAttributes.erase(NewAttributes.begin() + I); + --E; + continue; + } + } else { VarDecl *VD = cast<VarDecl>(New); unsigned Diag = cast<VarDecl>(Def)->isThisDeclarationADefinition() == VarDecl::TentativeDefinition @@ -10398,14 +10406,17 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, } } -Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { +Decl * +Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, + SkipBodyInfo *SkipBody) { assert(getCurFunctionDecl() == nullptr && "Function parsing confused"); assert(D.isFunctionDeclarator() && "Not a function declarator!"); Scope *ParentScope = FnBodyScope->getParent(); D.setFunctionDefinitionKind(FDK_Definition); - Decl *DP = HandleDeclarator(ParentScope, D, MultiTemplateParamsArg()); - return ActOnStartOfFunctionDef(FnBodyScope, DP); + Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists); + return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody); } void Sema::ActOnFinishInlineMethodDef(CXXMethodDecl *D) { @@ -10469,7 +10480,8 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, void Sema::CheckForFunctionRedefinition(FunctionDecl *FD, - const FunctionDecl *EffectiveDefinition) { + const FunctionDecl *EffectiveDefinition, + SkipBodyInfo *SkipBody) { // Don't complain if we're in GNU89 mode and the previous definition // was an extern inline function. const FunctionDecl *Definition = EffectiveDefinition; @@ -10481,17 +10493,20 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, return; // If we don't have a visible definition of the function, and it's inline or - // a template, it's OK to form another definition of it. - // - // FIXME: Should we skip the body of the function and use the old definition - // in this case? That may be necessary for functions that return local types - // through a deduced return type, or instantiate templates with local types. - if (!hasVisibleDefinition(Definition) && + // a template, skip the new definition. + if (SkipBody && !hasVisibleDefinition(Definition) && (Definition->getFormalLinkage() == InternalLinkage || Definition->isInlined() || Definition->getDescribedFunctionTemplate() || - Definition->getNumTemplateParameterLists())) + Definition->getNumTemplateParameterLists())) { + SkipBody->ShouldSkip = true; + if (auto *TD = Definition->getDescribedFunctionTemplate()) + makeMergedDefinitionVisible(TD, FD->getLocation()); + else + makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition), + FD->getLocation()); return; + } if (getLangOpts().GNUMode && Definition->isInlineSpecified() && Definition->getStorageClass() == SC_Extern) @@ -10552,7 +10567,8 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, } } -Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { +Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, + SkipBodyInfo *SkipBody) { // Clear the last template instantiation error context. LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation(); @@ -10564,6 +10580,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { FD = FunTmpl->getTemplatedDecl(); else FD = cast<FunctionDecl>(D); + + // See if this is a redefinition. + if (!FD->isLateTemplateParsed()) { + CheckForFunctionRedefinition(FD, nullptr, SkipBody); + + // If we're skipping the body, we're done. Don't enter the scope. + if (SkipBody && SkipBody->ShouldSkip) + return D; + } + // If we are instantiating a generic lambda call operator, push // a LambdaScopeInfo onto the function stack. But use the information // that's already been calculated (ActOnLambdaExpr) to prime the current @@ -10583,10 +10609,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // Enter a new function scope PushFunctionScope(); - // See if this is a redefinition. - if (!FD->isLateTemplateParsed()) - CheckForFunctionRedefinition(FD); - // Builtin functions cannot be defined. if (unsigned BuiltinID = FD->getBuiltinID()) { if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) && diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 85e8e318959..527005094c9 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -6472,24 +6472,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S, return NewDecl; } -Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, - MultiTemplateParamsArg TemplateParameterLists, - Declarator &D) { - assert(getCurFunctionDecl() == nullptr && "Function parsing confused"); - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - - if (FTI.hasPrototype) { - // FIXME: Diagnose arguments without names in C. - } - - Scope *ParentScope = FnBodyScope->getParent(); - - D.setFunctionDefinitionKind(FDK_Definition); - Decl *DP = HandleDeclarator(ParentScope, D, - TemplateParameterLists); - return ActOnStartOfFunctionDef(FnBodyScope, DP); -} - /// \brief Strips various properties off an implicit instantiation /// that has just been explicitly specialized. static void StripImplicitInstantiation(NamedDecl *D) { |