diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 133 |
1 files changed, 97 insertions, 36 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 38de2b204a8..bc46aae0a6b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1105,7 +1105,7 @@ void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { TUScope->AddDecl(D); } -bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, +bool Sema::isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S, bool ExplicitInstantiationOrSpecialization) { return IdResolver.isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization); @@ -2277,7 +2277,8 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) { /// merged with. /// /// Returns true if there was an error, false otherwise. -bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { +bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, + bool MergeTypeWithOld) { // Verify the old decl was also a function. FunctionDecl *Old = 0; if (FunctionTemplateDecl *OldFunctionTemplate @@ -2614,7 +2615,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { } if (OldQTypeForComparison == NewQType) - return MergeCompatibleFunctionDecls(New, Old, S); + return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); // Fall through for conflicting redeclarations and redefinitions. } @@ -2626,7 +2627,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { const FunctionType *OldFuncType = OldQType->getAs<FunctionType>(); const FunctionType *NewFuncType = NewQType->getAs<FunctionType>(); const FunctionProtoType *OldProto = 0; - if (isa<FunctionNoProtoType>(NewFuncType) && + if (MergeTypeWithOld && isa<FunctionNoProtoType>(NewFuncType) && (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) { // The old declaration provided a function prototype, but the // new declaration does not. Merge in the prototype. @@ -2659,7 +2660,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { New->setParams(Params); } - return MergeCompatibleFunctionDecls(New, Old, S); + return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); } // GNU C permits a K&R definition to follow a prototype declaration @@ -2717,9 +2718,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { diag::note_previous_declaration); } - New->setType(Context.getFunctionType(MergedReturn, ArgTypes, - OldProto->getExtProtoInfo())); - return MergeCompatibleFunctionDecls(New, Old, S); + if (MergeTypeWithOld) + New->setType(Context.getFunctionType(MergedReturn, ArgTypes, + OldProto->getExtProtoInfo())); + return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); } // Fall through to diagnose conflicting types. @@ -2771,7 +2773,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { /// /// \returns false bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, - Scope *S) { + Scope *S, bool MergeTypeWithOld) { // Merge the attributes mergeDeclAttributes(New, Old); @@ -2794,9 +2796,10 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, return MergeCXXFunctionDecl(New, Old, S); // Merge the function types so the we get the composite types for the return - // and argument types. + // and argument types. Per C11 6.2.7/4, only update the type if the old decl + // was visible. QualType Merged = Context.mergeTypes(Old->getType(), New->getType()); - if (!Merged.isNull()) + if (!Merged.isNull() && MergeTypeWithOld) New->setType(Merged); return false; @@ -2830,7 +2833,8 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, /// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back /// to here in AddInitializerToDecl. We can't check them before the initializer /// is attached. -void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) { +void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, + bool MergeTypeWithOld) { if (New->isInvalidDecl() || Old->isInvalidDecl()) return; @@ -2871,6 +2875,30 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) { MergedT = Context.mergeTypes(New->getType(), Old->getType()); } if (MergedT.isNull()) { + // It's OK if we couldn't merge types if either type is dependent, for a + // block-scope variable. In other cases (static data members of class + // templates, variable templates, ...), we require the types to be + // equivalent. + // FIXME: The C++ standard doesn't say anything about this. + if ((New->getType()->isDependentType() || + Old->getType()->isDependentType()) && New->isLocalVarDecl()) { + // If the old type was dependent, we can't merge with it, so the new type + // becomes dependent for now. We'll reproduce the original type when we + // instantiate the TypeSourceInfo for the variable. + if (!New->getType()->isDependentType() && MergeTypeWithOld) + New->setType(Context.DependentTy); + return; + } + + // FIXME: Even if this merging succeeds, some other non-visible declaration + // of this variable might have an incompatible type. For instance: + // + // extern int arr[]; + // void f() { extern int arr[2]; } + // void g() { extern int arr[3]; } + // + // Neither C nor C++ requires a diagnostic for this, but we should still try + // to diagnose it. Diag(New->getLocation(), diag::err_redefinition_different_type) << New->getDeclName() << New->getType() << Old->getType(); Diag(Old->getLocation(), diag::note_previous_definition); @@ -2879,7 +2907,7 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) { // Don't actually update the type on the new declaration if the old // declaration was a extern declaration in a different scope. - if (!OldWasHidden) + if (MergeTypeWithOld) New->setType(MergedT); } @@ -2892,7 +2920,7 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) { /// definitions here, since the initializer hasn't been attached. /// void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, - bool PreviousWasHidden) { + bool MergeTypeWithPrevious) { // If the new decl is already invalid, don't do any other checking. if (New->isInvalidDecl()) return; @@ -2935,7 +2963,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, } // Merge the types. - MergeVarDeclTypes(New, Old, PreviousWasHidden); + MergeVarDeclTypes(New, Old, MergeTypeWithPrevious); if (New->isInvalidDecl()) return; @@ -4172,26 +4200,31 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, // See if this is a redefinition of a variable in the same scope. if (!D.getCXXScopeSpec().isSet()) { bool IsLinkageLookup = false; + bool CreateBuiltins = false; // If the declaration we're planning to build will be a function // or object with linkage, then look for another declaration with // linkage (C99 6.2.2p4-5 and C++ [basic.link]p6). + // + // If the declaration we're planning to build will be declared with + // external linkage in the translation unit, create any builtin with + // the same name. if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) /* Do nothing*/; - else if (R->isFunctionType()) { - if (CurContext->isFunctionOrMethod() || - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) - IsLinkageLookup = true; - } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) - IsLinkageLookup = true; - else if (CurContext->getRedeclContext()->isTranslationUnit() && - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) + else if (CurContext->isFunctionOrMethod() && + (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern || + R->isFunctionType())) { IsLinkageLookup = true; + CreateBuiltins = + CurContext->getEnclosingNamespaceContext()->isTranslationUnit(); + } else if (CurContext->getRedeclContext()->isTranslationUnit() && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) + CreateBuiltins = true; if (IsLinkageLookup) Previous.clear(LookupRedeclarationWithLinkage); - LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup); + LookupName(Previous, S, CreateBuiltins); } else { // Something like "int foo::x;" LookupQualifiedName(Previous, DC); @@ -5241,6 +5274,14 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, Previous, DC, S, shouldConsiderLinkage(NewVD), IsExplicitSpecialization || IsVariableTemplateSpecialization); + // Check whether the previous declaration is in the same block scope. This + // affects whether we merge types with it, per C++11 [dcl.array]p3. + if (getLangOpts().CPlusPlus && + NewVD->isLocalVarDecl() && NewVD->hasExternalStorage()) + NewVD->setPreviousDeclInSameBlockScope( + Previous.isSingleResult() && !Previous.isShadowed() && + isDeclInScope(Previous.getFoundDecl(), DC, S, false)); + if (!getLangOpts().CPlusPlus) { D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); } else { @@ -5714,7 +5755,6 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, // If we did not find anything by this name, look for a non-visible // extern "C" declaration with the same name. // - // Clang has a lot of problems with extern local declarations. // The actual standards text here is: // // C++11 [basic.link]p6: @@ -5726,6 +5766,11 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, // block scope declaration declares that same entity and // receives the linkage of the previous declaration. // + // C++11 [dcl.array]p3: + // If there is a preceding declaration of the entity in the same + // scope in which the bound was specified, an omitted array bound + // is taken to be the same as in that earlier declaration. + // // C11 6.2.7p4: // For an identifier with internal or external linkage declared // in a scope in which a prior declaration of that identifier is @@ -5735,16 +5780,22 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, // // The most important point here is that we're not allowed to // update our understanding of the type according to declarations - // not in scope. - bool PreviousWasHidden = - Previous.empty() && - checkForConflictWithNonVisibleExternC(*this, NewVD, Previous); + // not in scope (in C++) or not visible (in C). + bool MergeTypeWithPrevious; + if (Previous.empty() && + checkForConflictWithNonVisibleExternC(*this, NewVD, Previous)) + MergeTypeWithPrevious = false; + else + MergeTypeWithPrevious = + !Previous.isShadowed() && + (!getLangOpts().CPlusPlus || NewVD->isPreviousDeclInSameBlockScope() || + !NewVD->getLexicalDeclContext()->isFunctionOrMethod()); // Filter out any non-conflicting previous declarations. filterNonConflictingPreviousDecls(Context, NewVD, Previous); if (!Previous.empty()) { - MergeVarDecl(NewVD, Previous, PreviousWasHidden); + MergeVarDecl(NewVD, Previous, MergeTypeWithPrevious); return true; } return false; @@ -6749,7 +6800,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewFD), isExplicitSpecialization || isFunctionTemplateSpecialization); - + // Handle GNU asm-label extension (encoded as an attribute). if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. @@ -6870,9 +6921,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!NewFD->isInvalidDecl()) D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization)); - // Make graceful recovery from an invalid redeclaration. else if (!Previous.empty()) - D.setRedeclaration(true); + // Make graceful recovery from an invalid redeclaration. + D.setRedeclaration(true); assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); @@ -7230,6 +7281,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, assert(!NewFD->getResultType()->isVariablyModifiedType() && "Variably modified return types are not handled here"); + // Determine whether the type of this function should be merged with + // a previous visible declaration. This never happens for functions in C++, + // and always happens in C if the previous declaration was visible. + bool MergeTypeWithPrevious = !getLangOpts().CPlusPlus && + !Previous.isShadowed(); + // Filter out any non-conflicting previous declarations. filterNonConflictingPreviousDecls(Context, NewFD, Previous); @@ -7293,6 +7350,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // declaration, and thus redeclares that entity... Redeclaration = true; OldDecl = Previous.getFoundDecl(); + MergeTypeWithPrevious = false; // ... except in the presence of __attribute__((overloadable)). if (OldDecl->hasAttr<OverloadableAttr>()) { @@ -7354,7 +7412,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (Redeclaration) { // NewFD and OldDecl represent declarations that need to be // merged. - if (MergeFunctionDecl(NewFD, OldDecl, S)) { + if (MergeFunctionDecl(NewFD, OldDecl, S, MergeTypeWithPrevious)) { NewFD->setInvalidDecl(); return Redeclaration; } @@ -7936,8 +7994,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. - if (VarDecl *Old = VDecl->getPreviousDecl()) - MergeVarDeclTypes(VDecl, Old, /*OldWasHidden*/ false); + if (VarDecl *Old = VDecl->getPreviousDecl()) { + // We never need to merge the type, because we cannot form an incomplete + // array of auto, nor deduce such a type. + MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/false); + } // Check the deduced type is valid for a variable declaration. CheckVariableDeclarationType(VDecl); |

