diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-08-13 18:18:50 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-08-13 18:18:50 +0000 |
commit | 1c34fb78e7ebb9956c4282a5247a949869e6c09c (patch) | |
tree | e0bbcc06c58ed3c975834e73b00bb4b053f80f94 /clang/lib | |
parent | c8d710cc82ee56cc59fb9b378b44623dcc53fd15 (diff) | |
download | bcm5719-llvm-1c34fb78e7ebb9956c4282a5247a949869e6c09c.tar.gz bcm5719-llvm-1c34fb78e7ebb9956c4282a5247a949869e6c09c.zip |
Fix implementation of C11 6.2.7/4 and C++11 [dcl.array]p3:
When a local extern declaration redeclares some other entity, the type of that
entity is merged with the prior type if the prior declaration is visible (in C)
or is declared in the same scope (in C++).
- Make LookupRedeclarationWithLinkage actually work in C++, use it in the right
set of cases, and make it track whether it found a shadowed declaration.
- Track whether we found a declaration in the same scope (for C++) including
across serialization and template instantiation.
llvm-svn: 188307
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 133 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 4 |
5 files changed, 136 insertions, 44 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); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index d0bb9f6abe6..3ad596c6b23 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -852,6 +852,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup"); DeclarationName Name = R.getLookupName(); + Sema::LookupNameKind NameKind = R.getLookupKind(); // If this is the name of an implicitly-declared special member function, // go through the scope stack to implicitly declare @@ -889,6 +890,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // UnqualUsingDirectiveSet UDirs; bool VisitedUsingDirectives = false; + bool LeftStartingScope = false; DeclContext *OutsideOfTemplateParamDC = 0; for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); @@ -897,6 +899,20 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { if (NamedDecl *ND = R.getAcceptableDecl(*I)) { + if (NameKind == LookupRedeclarationWithLinkage) { + // Determine whether this (or a previous) declaration is + // out-of-scope. + if (!LeftStartingScope && !Initial->isDeclScope(*I)) + LeftStartingScope = true; + + // If we found something outside of our starting scope that + // does not have linkage, skip it. + if (LeftStartingScope && !((*I)->hasLinkage())) { + R.setShadowed(); + continue; + } + } + Found = true; R.addDecl(ND); } @@ -909,7 +925,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return true; } - if (R.getLookupKind() == LookupLocalFriendName && !S->isClassScope()) { + if (NameKind == LookupLocalFriendName && !S->isClassScope()) { // C++11 [class.friend]p11: // If a friend declaration appears in a local class and the name // specified is an unqualified name, a prior declaration is @@ -1019,7 +1035,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { if (!S) return false; // If we are looking for members, no need to look into global/namespace scope. - if (R.getLookupKind() == LookupMemberName) + if (NameKind == LookupMemberName) return false; // Collect UsingDirectiveDecls in all scopes, and recursively all @@ -1291,8 +1307,10 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { // If we found something outside of our starting scope that // does not have linkage, skip it. - if (LeftStartingScope && !((*I)->hasLinkage())) + if (LeftStartingScope && !((*I)->hasLinkage())) { + R.setShadowed(); continue; + } } else if (NameKind == LookupObjCImplicitSelfParam && !isa<ImplicitParamDecl>(*I)) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5766afa1011..c7242aa5f99 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -973,7 +973,8 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) { // FIXME: This, and ForVarTemplate, is a hack that is probably unnecessary. // We should use a simplified version of VisitVarDecl. - VarDecl *VarInst = cast_or_null<VarDecl>(VisitVarDecl(Pattern, /*ForVarTemplate=*/true)); + VarDecl *VarInst = + cast_or_null<VarDecl>(VisitVarDecl(Pattern, /*ForVarTemplate=*/ true)); DeclContext *DC = Owner; @@ -3336,6 +3337,8 @@ void Sema::BuildVariableInstantiation( NewVar->setInitStyle(OldVar->getInitStyle()); NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl()); NewVar->setConstexpr(OldVar->isConstexpr()); + NewVar->setPreviousDeclInSameBlockScope( + OldVar->isPreviousDeclInSameBlockScope()); NewVar->setAccess(OldVar->getAccess()); if (!OldVar->isStaticDataMember()) { @@ -3348,13 +3351,18 @@ void Sema::BuildVariableInstantiation( if (NewVar->hasAttrs()) CheckAlignasUnderalignment(NewVar); - // FIXME: In theory, we could have a previous declaration for variables that - // are not static data members. - // FIXME: having to fake up a LookupResult is dumb. LookupResult Previous(*this, NewVar->getDeclName(), NewVar->getLocation(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); - if (!isa<VarTemplateSpecializationDecl>(NewVar)) + if (NewVar->getLexicalDeclContext()->isFunctionOrMethod() && + OldVar->getPreviousDecl()) { + // We have a previous declaration. Use that one, so we merge with the + // right type. + if (NamedDecl *NewPrev = FindInstantiatedDecl( + NewVar->getLocation(), OldVar->getPreviousDecl(), TemplateArgs)) + Previous.addDecl(NewPrev); + } else if (!isa<VarTemplateSpecializationDecl>(NewVar) && + OldVar->hasLinkage()) LookupQualifiedName(Previous, NewVar->getDeclContext(), false); CheckVariableDeclaration(NewVar, Previous); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index b6dadd68c9b..1eef54b1421 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -939,6 +939,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->VarDeclBits.CXXForRangeDecl = Record[Idx++]; VD->VarDeclBits.ARCPseudoStrong = Record[Idx++]; VD->VarDeclBits.IsConstexpr = Record[Idx++]; + VD->VarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++]; VD->setCachedLinkage(Linkage(Record[Idx++])); // Only true variables (not parameters or implicit parameters) can be merged. diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index bb7fd1edf6e..c9f3a6541f8 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -703,6 +703,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { Record.push_back(D->isCXXForRangeDecl()); Record.push_back(D->isARCPseudoStrong()); Record.push_back(D->isConstexpr()); + Record.push_back(D->isPreviousDeclInSameBlockScope()); Record.push_back(D->getLinkageInternal()); if (D->getInit()) { @@ -737,6 +738,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { !isa<ParmVarDecl>(D) && !isa<VarTemplateSpecializationDecl>(D) && !D->isConstexpr() && + !D->isPreviousDeclInSameBlockScope() && !SpecInfo) AbbrevToUse = Writer.getDeclVarAbbrev(); @@ -1622,6 +1624,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isCXXForRangeDecl Abv->Add(BitCodeAbbrevOp(0)); // isARCPseudoStrong Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr + Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope Abv->Add(BitCodeAbbrevOp(0)); // Linkage Abv->Add(BitCodeAbbrevOp(0)); // HasInit Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo @@ -1701,6 +1704,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr + Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasInit Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasMemberSpecInfo |