r284008 - Reinstate r283887 and r283882.

Manman via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 12 14:05:46 PDT 2016


> On Oct 12, 2016, at 1:39 PM, Vassil Vassilev <v.g.vassilev at gmail.com> wrote:
> 
> Hi Manman,
> On 12/10/16 20:28, Manman wrote:
>> Hi Vassil,
>> 
>> Any change between this commit and “r283887 + r283882”?
> The only extra change is in:
> 
> +  bool isThisDeclarationADemotedDefinition() const {
> +    return isa<ParmVarDecl>(this) ? false :
> +      NonParmVarDeclBits.IsThisDeclarationADemotedDefinition;
> +  }
> 
> The old patch failed because we read the IsThisDeclarationADemotedDefinition bit of ParmVarDecls. We allow demoting only VarDecls, which are not ParmVarDecls, and thus we serialize/deserialize this bit only for non ParmVarDecls. Reading the IsThisDeclarationADemotedDefinition of ParmVarDecls caused random behavior.

Thanks,

Manman

> 
> Cheers,
> Vassil
>> And what was the issue that caused the revert?
>> 
>> Thanks,
>> Manman
>> 
>>> On Oct 12, 2016, at 4:57 AM, Vassil Vassilev via cfe-commits <cfe-commits at lists.llvm.org> wrote:
>>> 
>>> Author: vvassilev
>>> Date: Wed Oct 12 06:57:08 2016
>>> New Revision: 284008
>>> 
>>> URL: http://llvm.org/viewvc/llvm-project?rev=284008&view=rev
>>> Log:
>>> Reinstate r283887 and r283882.
>>> 
>>> Original message:
>>> "[modules] PR28752: Do not instantiate variable declarations which are not visible.
>>> 
>>> https://reviews.llvm.org/D24508
>>> 
>>> Patch developed in collaboration with Richard Smith!"
>>> 
>>> Added:
>>>    cfe/trunk/test/Modules/Inputs/PR28752/
>>>    cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/
>>>    cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/b.h
>>>    cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/c.h
>>>    cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/module.modulemap
>>>    cfe/trunk/test/Modules/Inputs/PR28752/a.h
>>>    cfe/trunk/test/Modules/Inputs/PR28752/module.modulemap
>>>    cfe/trunk/test/Modules/Inputs/PR28752/vector
>>>    cfe/trunk/test/Modules/pr28752.cpp
>>> Modified:
>>>    cfe/trunk/include/clang/AST/Decl.h
>>>    cfe/trunk/lib/AST/Decl.cpp
>>>    cfe/trunk/lib/Sema/SemaDecl.cpp
>>>    cfe/trunk/lib/Sema/SemaTemplate.cpp
>>>    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
>>>    cfe/trunk/lib/Sema/SemaType.cpp
>>>    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
>>>    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
>>> 
>>> Modified: cfe/trunk/include/clang/AST/Decl.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=284008&r1=284007&r2=284008&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/AST/Decl.h (original)
>>> +++ cfe/trunk/include/clang/AST/Decl.h Wed Oct 12 06:57:08 2016
>>> @@ -865,6 +865,11 @@ protected:
>>> 
>>>     unsigned : NumVarDeclBits;
>>> 
>>> +    // FIXME: We need something similar to CXXRecordDecl::DefinitionData.
>>> +    /// \brief Whether this variable is a definition which was demoted due to
>>> +    /// module merge.
>>> +    unsigned IsThisDeclarationADemotedDefinition : 1;
>>> +
>>>     /// \brief Whether this variable is the exception variable in a C++ catch
>>>     /// or an Objective-C @catch statement.
>>>     unsigned ExceptionVar : 1;
>>> @@ -1198,12 +1203,28 @@ public:
>>>   InitializationStyle getInitStyle() const {
>>>     return static_cast<InitializationStyle>(VarDeclBits.InitStyle);
>>>   }
>>> -
>>>   /// \brief Whether the initializer is a direct-initializer (list or call).
>>>   bool isDirectInit() const {
>>>     return getInitStyle() != CInit;
>>>   }
>>> 
>>> +  /// \brief If this definition should pretend to be a declaration.
>>> +  bool isThisDeclarationADemotedDefinition() const {
>>> +    return isa<ParmVarDecl>(this) ? false :
>>> +      NonParmVarDeclBits.IsThisDeclarationADemotedDefinition;
>>> +  }
>>> +
>>> +  /// \brief This is a definition which should be demoted to a declaration.
>>> +  ///
>>> +  /// In some cases (mostly module merging) we can end up with two visible
>>> +  /// definitions one of which needs to be demoted to a declaration to keep
>>> +  /// the AST invariants.
>>> +  void demoteThisDefinitionToDeclaration() {
>>> +    assert (isThisDeclarationADefinition() && "Not a definition!");
>>> +    assert (!isa<ParmVarDecl>(this) && "Cannot demote ParmVarDecls!");
>>> +    NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = 1;
>>> +  }
>>> +
>>>   /// \brief Determine whether this variable is the exception variable in a
>>>   /// C++ catch statememt or an Objective-C \@catch statement.
>>>   bool isExceptionVariable() const {
>>> @@ -1302,6 +1323,10 @@ public:
>>>     NonParmVarDeclBits.PreviousDeclInSameBlockScope = Same;
>>>   }
>>> 
>>> +  /// \brief Retrieve the variable declaration from which this variable could
>>> +  /// be instantiated, if it is an instantiation (rather than a non-template).
>>> +  VarDecl *getTemplateInstantiationPattern() const;
>>> +
>>>   /// \brief If this variable is an instantiated static data member of a
>>>   /// class template specialization, returns the templated static data member
>>>   /// from which it was instantiated.
>>> 
>>> Modified: cfe/trunk/lib/AST/Decl.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=284008&r1=284007&r2=284008&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/AST/Decl.cpp (original)
>>> +++ cfe/trunk/lib/AST/Decl.cpp Wed Oct 12 06:57:08 2016
>>> @@ -1926,6 +1926,9 @@ VarDecl::isThisDeclarationADefinition(AS
>>>   //
>>>   // FIXME: How do you declare (but not define) a partial specialization of
>>>   // a static data member template outside the containing class?
>>> +  if (isThisDeclarationADemotedDefinition())
>>> +    return DeclarationOnly;
>>> +
>>>   if (isStaticDataMember()) {
>>>     if (isOutOfLine() &&
>>>         !(getCanonicalDecl()->isInline() &&
>>> @@ -2250,6 +2253,56 @@ bool VarDecl::checkInitIsICE() const {
>>>   return Eval->IsICE;
>>> }
>>> 
>>> +VarDecl *VarDecl::getTemplateInstantiationPattern() const {
>>> +  // If it's a variable template specialization, find the template or partial
>>> +  // specialization from which it was instantiated.
>>> +  if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(this)) {
>>> +    auto From = VDTemplSpec->getInstantiatedFrom();
>>> +    if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
>>> +      while (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate()) {
>>> +        if (NewVTD->isMemberSpecialization())
>>> +          break;
>>> +        VTD = NewVTD;
>>> +      }
>>> +      return VTD->getTemplatedDecl()->getDefinition();
>>> +    }
>>> +    if (auto *VTPSD =
>>> +            From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
>>> +      while (auto *NewVTPSD = VTPSD->getInstantiatedFromMember()) {
>>> +        if (NewVTPSD->isMemberSpecialization())
>>> +          break;
>>> +        VTPSD = NewVTPSD;
>>> +      }
>>> +      return VTPSD->getDefinition();
>>> +    }
>>> +  }
>>> +
>>> +  if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
>>> +    if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
>>> +      VarDecl *VD = getInstantiatedFromStaticDataMember();
>>> +      while (auto *NewVD = VD->getInstantiatedFromStaticDataMember())
>>> +        VD = NewVD;
>>> +      return VD->getDefinition();
>>> +    }
>>> +  }
>>> +
>>> +  if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) {
>>> +
>>> +    while (VarTemplate->getInstantiatedFromMemberTemplate()) {
>>> +      if (VarTemplate->isMemberSpecialization())
>>> +        break;
>>> +      VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate();
>>> +    }
>>> +
>>> +    assert((!VarTemplate->getTemplatedDecl() ||
>>> +            !isTemplateInstantiation(getTemplateSpecializationKind())) &&
>>> +           "couldn't find pattern for variable instantiation");
>>> +
>>> +    return VarTemplate->getTemplatedDecl();
>>> +  }
>>> +  return nullptr;
>>> +}
>>> +
>>> VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
>>>   if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
>>>     return cast<VarDecl>(MSI->getInstantiatedFrom());
>>> 
>>> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=284008&r1=284007&r2=284008&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Oct 12 06:57:08 2016
>>> @@ -9708,6 +9708,22 @@ void Sema::AddInitializerToDecl(Decl *Re
>>>          VDecl->getDeclContext()->isDependentContext())) {
>>>       // The previous definition is hidden, and multiple definitions are
>>>       // permitted (in separate TUs). Form another definition of it.
>>> +      if (!isa<ParmVarDecl>(VDecl)) {
>>> +        // Demote the newly parsed definition to a fake declaration.
>>> +        if (!VDecl->isThisDeclarationADemotedDefinition())
>>> +          VDecl->demoteThisDefinitionToDeclaration();
>>> +
>>> +        // Make the definition visible from the point of the demotion on.
>>> +        assert (!Hidden || Def == Hidden &&
>>> +                "We were suggested another hidden definition!");
>>> +        makeMergedDefinitionVisible(Def, VDecl->getLocation());
>>> +
>>> +        // If this is a variable template definition, make its enclosing template
>>> +        // visible.
>>> +        if (VarDecl *VarPattern = Def->getTemplateInstantiationPattern())
>>> +          if (VarPattern->isThisDeclarationADefinition())
>>> +            makeMergedDefinitionVisible(VarPattern, VDecl->getLocation());
>>> +      }
>>>     } else {
>>>       Diag(VDecl->getLocation(), diag::err_redefinition)
>>>         << VDecl->getDeclName();
>>> 
>>> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=284008&r1=284007&r2=284008&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Oct 12 06:57:08 2016
>>> @@ -466,10 +466,14 @@ bool Sema::DiagnoseUninstantiableTemplat
>>>                                           const NamedDecl *PatternDef,
>>>                                           TemplateSpecializationKind TSK,
>>>                                           bool Complain /*= true*/) {
>>> -  assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation));
>>> +  assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation) ||
>>> +         isa<VarDecl>(Instantiation));
>>> 
>>> -  if (PatternDef && (isa<FunctionDecl>(PatternDef)
>>> -                     || !cast<TagDecl>(PatternDef)->isBeingDefined())) {
>>> +  bool IsEntityBeingDefined = false;
>>> +  if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(PatternDef))
>>> +    IsEntityBeingDefined = TD->isBeingDefined();
>>> +
>>> +  if (PatternDef && !IsEntityBeingDefined) {
>>>     NamedDecl *SuggestedDef = nullptr;
>>>     if (!hasVisibleDefinition(const_cast<NamedDecl*>(PatternDef), &SuggestedDef,
>>>                               /*OnlyNeedComplete*/false)) {
>>> @@ -486,13 +490,14 @@ bool Sema::DiagnoseUninstantiableTemplat
>>>   if (!Complain || (PatternDef && PatternDef->isInvalidDecl()))
>>>     return true;
>>> 
>>> +  llvm::Optional<unsigned> Note;
>>>   QualType InstantiationTy;
>>>   if (TagDecl *TD = dyn_cast<TagDecl>(Instantiation))
>>>     InstantiationTy = Context.getTypeDeclType(TD);
>>>   if (PatternDef) {
>>>     Diag(PointOfInstantiation,
>>>          diag::err_template_instantiate_within_definition)
>>> -      << (TSK != TSK_ImplicitInstantiation)
>>> +      << /*implicit|explicit*/(TSK != TSK_ImplicitInstantiation)
>>>       << InstantiationTy;
>>>     // Not much point in noting the template declaration here, since
>>>     // we're lexically inside it.
>>> @@ -501,28 +506,44 @@ bool Sema::DiagnoseUninstantiableTemplat
>>>     if (isa<FunctionDecl>(Instantiation)) {
>>>       Diag(PointOfInstantiation,
>>>            diag::err_explicit_instantiation_undefined_member)
>>> -        << 1 << Instantiation->getDeclName() << Instantiation->getDeclContext();
>>> +        << /*member function*/ 1 << Instantiation->getDeclName()
>>> +        << Instantiation->getDeclContext();
>>> +      Note = diag::note_explicit_instantiation_here;
>>>     } else {
>>> +      assert(isa<TagDecl>(Instantiation) && "Must be a TagDecl!");
>>>       Diag(PointOfInstantiation,
>>>            diag::err_implicit_instantiate_member_undefined)
>>>         << InstantiationTy;
>>> +      Note = diag::note_member_declared_at;
>>>     }
>>> -    Diag(Pattern->getLocation(), isa<FunctionDecl>(Instantiation)
>>> -                                     ? diag::note_explicit_instantiation_here
>>> -                                     : diag::note_member_declared_at);
>>>   } else {
>>> -    if (isa<FunctionDecl>(Instantiation))
>>> +    if (isa<FunctionDecl>(Instantiation)) {
>>>       Diag(PointOfInstantiation,
>>>            diag::err_explicit_instantiation_undefined_func_template)
>>>         << Pattern;
>>> -    else
>>> +      Note = diag::note_explicit_instantiation_here;
>>> +    } else if (isa<TagDecl>(Instantiation)) {
>>>       Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
>>>         << (TSK != TSK_ImplicitInstantiation)
>>>         << InstantiationTy;
>>> -    Diag(Pattern->getLocation(), isa<FunctionDecl>(Instantiation)
>>> -                                     ? diag::note_explicit_instantiation_here
>>> -                                     : diag::note_template_decl_here);
>>> +      Note = diag::note_template_decl_here;
>>> +    } else {
>>> +      assert(isa<VarDecl>(Instantiation) && "Must be a VarDecl!");
>>> +      if (isa<VarTemplateSpecializationDecl>(Instantiation)) {
>>> +        Diag(PointOfInstantiation,
>>> +             diag::err_explicit_instantiation_undefined_var_template)
>>> +          << Instantiation;
>>> +        Instantiation->setInvalidDecl();
>>> +      } else
>>> +        Diag(PointOfInstantiation,
>>> +             diag::err_explicit_instantiation_undefined_member)
>>> +          << /*static data member*/ 2 << Instantiation->getDeclName()
>>> +          << Instantiation->getDeclContext();
>>> +      Note = diag::note_explicit_instantiation_here;
>>> +    }
>>>   }
>>> +  if (Note) // Diagnostics were emitted.
>>> +    Diag(Pattern->getLocation(), Note.getValue());
>>> 
>>>   // In general, Instantiation isn't marked invalid to get more than one
>>>   // error for multiple undefined instantiations. But the code that does
>>> 
>>> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=284008&r1=284007&r2=284008&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Oct 12 06:57:08 2016
>>> @@ -4068,6 +4068,10 @@ void Sema::InstantiateVariableDefinition
>>>       PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
>>>                                           "instantiating variable initializer");
>>> 
>>> +      // The instantiation is visible here, even if it was first declared in an
>>> +      // unimported module.
>>> +      Var->setHidden(false);
>>> +
>>>       // If we're performing recursive template instantiation, create our own
>>>       // queue of pending implicit instantiations that we will instantiate
>>>       // later, while we're still within our own instantiation context.
>>> @@ -4116,33 +4120,17 @@ void Sema::InstantiateVariableDefinition
>>>     Def = PatternDecl->getDefinition();
>>>   }
>>> 
>>> -  // FIXME: Check that the definition is visible before trying to instantiate
>>> -  // it. This requires us to track the instantiation stack in order to know
>>> -  // which definitions should be visible.
>>> +  TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
>>> 
>>>   // If we don't have a definition of the variable template, we won't perform
>>>   // any instantiation. Rather, we rely on the user to instantiate this
>>>   // definition (or provide a specialization for it) in another translation
>>>   // unit.
>>> -  if (!Def) {
>>> -    if (DefinitionRequired) {
>>> -      if (VarSpec) {
>>> -        Diag(PointOfInstantiation,
>>> -             diag::err_explicit_instantiation_undefined_var_template) << Var;
>>> -        Var->setInvalidDecl();
>>> -      }
>>> -      else
>>> -        Diag(PointOfInstantiation,
>>> -             diag::err_explicit_instantiation_undefined_member)
>>> -            << 2 << Var->getDeclName() << Var->getDeclContext();
>>> -      Diag(PatternDecl->getLocation(),
>>> -           diag::note_explicit_instantiation_here);
>>> -    } else if (Var->getTemplateSpecializationKind()
>>> -                 == TSK_ExplicitInstantiationDefinition) {
>>> +  if (!Def && !DefinitionRequired) {
>>> +    if (TSK == TSK_ExplicitInstantiationDefinition) {
>>>       PendingInstantiations.push_back(
>>>         std::make_pair(Var, PointOfInstantiation));
>>> -    } else if (Var->getTemplateSpecializationKind()
>>> -                 == TSK_ImplicitInstantiation) {
>>> +    } else if (TSK == TSK_ImplicitInstantiation) {
>>>       // Warn about missing definition at the end of translation unit.
>>>       if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
>>>         Diag(PointOfInstantiation, diag::warn_var_template_missing)
>>> @@ -4151,12 +4139,20 @@ void Sema::InstantiateVariableDefinition
>>>         if (getLangOpts().CPlusPlus11)
>>>           Diag(PointOfInstantiation, diag::note_inst_declaration_hint) << Var;
>>>       }
>>> +      return;
>>>     }
>>> 
>>> -    return;
>>>   }
>>> 
>>> -  TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
>>> +  // FIXME: We need to track the instantiation stack in order to know which
>>> +  // definitions should be visible within this instantiation.
>>> +  // FIXME: Produce diagnostics when Var->getInstantiatedFromStaticDataMember().
>>> +  if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Var,
>>> +                                     /*InstantiatedFromMember*/false,
>>> +                                     PatternDecl, Def, TSK,
>>> +                                     /*Complain*/DefinitionRequired))
>>> +    return;
>>> +
>>> 
>>>   // Never instantiate an explicit specialization.
>>>   if (TSK == TSK_ExplicitSpecialization)
>>> 
>>> Modified: cfe/trunk/lib/Sema/SemaType.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=284008&r1=284007&r2=284008&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaType.cpp Wed Oct 12 06:57:08 2016
>>> @@ -6888,6 +6888,10 @@ bool Sema::hasVisibleDefinition(NamedDec
>>>     if (auto *Pattern = FD->getTemplateInstantiationPattern())
>>>       FD = Pattern;
>>>     D = FD->getDefinition();
>>> +  } else if (auto *VD = dyn_cast<VarDecl>(D)) {
>>> +    if (auto *Pattern = VD->getTemplateInstantiationPattern())
>>> +      VD = Pattern;
>>> +    D = VD->getDefinition();
>>>   }
>>>   assert(D && "missing definition for pattern of instantiated definition");
>>> 
>>> 
>>> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=284008&r1=284007&r2=284008&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
>>> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed Oct 12 06:57:08 2016
>>> @@ -1216,6 +1216,7 @@ ASTDeclReader::RedeclarableResult ASTDec
>>>   VD->VarDeclBits.TSCSpec = Record[Idx++];
>>>   VD->VarDeclBits.InitStyle = Record[Idx++];
>>>   if (!isa<ParmVarDecl>(VD)) {
>>> +    VD->NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = Record[Idx++];
>>>     VD->NonParmVarDeclBits.ExceptionVar = Record[Idx++];
>>>     VD->NonParmVarDeclBits.NRVOVariable = Record[Idx++];
>>>     VD->NonParmVarDeclBits.CXXForRangeDecl = Record[Idx++];
>>> @@ -3069,6 +3070,29 @@ void ASTDeclReader::attachPreviousDeclIm
>>> namespace clang {
>>> template<>
>>> void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
>>> +                                           Redeclarable<VarDecl> *D,
>>> +                                           Decl *Previous, Decl *Canon) {
>>> +  VarDecl *VD = static_cast<VarDecl*>(D);
>>> +  VarDecl *PrevVD = cast<VarDecl>(Previous);
>>> +  D->RedeclLink.setPrevious(PrevVD);
>>> +  D->First = PrevVD->First;
>>> +
>>> +  // We should keep at most one definition on the chain.
>>> +  if (VD->isThisDeclarationADefinition()) {
>>> +    for (VarDecl *CurD = PrevVD; CurD; CurD = CurD->getPreviousDecl()) {
>>> +      // If we find an already demoted definition, this we already visited this
>>> +      // part of the chain. Reduces the loop from quadratic-time to linear-time.
>>> +      if (CurD->isThisDeclarationADemotedDefinition() ||
>>> +          CurD->isThisDeclarationADefinition()) {
>>> +        VD->demoteThisDefinitionToDeclaration();
>>> +        break;
>>> +      }
>>> +    }
>>> +  }
>>> +}
>>> +
>>> +template<>
>>> +void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
>>>                                            Redeclarable<FunctionDecl> *D,
>>>                                            Decl *Previous, Decl *Canon) {
>>>   FunctionDecl *FD = static_cast<FunctionDecl*>(D);
>>> 
>>> Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=284008&r1=284007&r2=284008&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
>>> +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Wed Oct 12 06:57:08 2016
>>> @@ -894,6 +894,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl
>>>   Record.push_back(D->getTSCSpec());
>>>   Record.push_back(D->getInitStyle());
>>>   if (!isa<ParmVarDecl>(D)) {
>>> +    Record.push_back(D->isThisDeclarationADemotedDefinition());
>>>     Record.push_back(D->isExceptionVariable());
>>>     Record.push_back(D->isNRVOVariable());
>>>     Record.push_back(D->isCXXForRangeDecl());
>>> @@ -998,6 +999,8 @@ void ASTDeclWriter::VisitParmVarDecl(Par
>>>   // Check things we know are true of *every* PARM_VAR_DECL, which is more than
>>>   // just us assuming it.
>>>   assert(!D->getTSCSpec() && "PARM_VAR_DECL can't use TLS");
>>> +  assert(!D->isThisDeclarationADemotedDefinition()
>>> +         && "PARM_VAR_DECL can't be demoted definition.");
>>>   assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
>>>   assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var");
>>>   assert(D->getPreviousDecl() == nullptr && "PARM_VAR_DECL can't be redecl");
>>> @@ -1957,6 +1960,7 @@ void ASTWriter::WriteDeclAbbrevs() {
>>>   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // SClass
>>>   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // TSCSpec
>>>   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // InitStyle
>>> +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsThisDeclarationADemotedDefinition
>>>   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable
>>>   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable
>>>   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl
>>> 
>>> Added: cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/b.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/b.h?rev=284008&view=auto
>>> ==============================================================================
>>> --- cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/b.h (added)
>>> +++ cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/b.h Wed Oct 12 06:57:08 2016
>>> @@ -0,0 +1 @@
>>> +#include <vector>
>>> 
>>> Added: cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/c.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/c.h?rev=284008&view=auto
>>> ==============================================================================
>>>    (empty)
>>> 
>>> Added: cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/module.modulemap
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/module.modulemap?rev=284008&view=auto
>>> ==============================================================================
>>> --- cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/module.modulemap (added)
>>> +++ cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/module.modulemap Wed Oct 12 06:57:08 2016
>>> @@ -0,0 +1,5 @@
>>> +module b {
>>> +  module "b.h" { header "b.h" export * }
>>> +  module "c.h" { header "c.h" export * }
>>> +  export *
>>> +}
>>> 
>>> Added: cfe/trunk/test/Modules/Inputs/PR28752/a.h
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR28752/a.h?rev=284008&view=auto
>>> ==============================================================================
>>> --- cfe/trunk/test/Modules/Inputs/PR28752/a.h (added)
>>> +++ cfe/trunk/test/Modules/Inputs/PR28752/a.h Wed Oct 12 06:57:08 2016
>>> @@ -0,0 +1 @@
>>> +#include <vector>
>>> 
>>> Added: cfe/trunk/test/Modules/Inputs/PR28752/module.modulemap
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR28752/module.modulemap?rev=284008&view=auto
>>> ==============================================================================
>>> --- cfe/trunk/test/Modules/Inputs/PR28752/module.modulemap (added)
>>> +++ cfe/trunk/test/Modules/Inputs/PR28752/module.modulemap Wed Oct 12 06:57:08 2016
>>> @@ -0,0 +1 @@
>>> +module a { header "a.h" export * }
>>> 
>>> Added: cfe/trunk/test/Modules/Inputs/PR28752/vector
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR28752/vector?rev=284008&view=auto
>>> ==============================================================================
>>> --- cfe/trunk/test/Modules/Inputs/PR28752/vector (added)
>>> +++ cfe/trunk/test/Modules/Inputs/PR28752/vector Wed Oct 12 06:57:08 2016
>>> @@ -0,0 +1,28 @@
>>> +#ifndef VECTOR
>>> +#define VECTOR
>>> +template <bool, typename> struct B;
>>> +template <typename _Tp> struct B<true, _Tp> { typedef _Tp type; };
>>> +namespace std {
>>> +template <typename> struct D {
>>> +
>>> +  template <typename _Alloc2> struct F {
>>> +    static const bool value = 0;
>>> +  };
>>> +
>>> +  template <typename _Alloc2>
>>> +  typename B<F<_Alloc2>::value, _Alloc2>::type _S_select(_Alloc2);
>>> +  template <typename _Alloc2>
>>> +  static
>>> +  typename B<!F<_Alloc2>::value, _Alloc2>::type _S_select(_Alloc2);
>>> +};
>>> +template <typename _Alloc>
>>> +template <typename _Alloc2>
>>> +const bool D<_Alloc>::F<_Alloc2>::value;
>>> +
>>> +template <typename> class vector {
>>> +public:
>>> +  vector(int);
>>> +  vector(vector &) : vector(D<bool>::_S_select((bool)0)) {}
>>> +};
>>> +}
>>> +#endif // VECTOR
>>> \ No newline at end of file
>>> 
>>> Added: cfe/trunk/test/Modules/pr28752.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/pr28752.cpp?rev=284008&view=auto
>>> ==============================================================================
>>> --- cfe/trunk/test/Modules/pr28752.cpp (added)
>>> +++ cfe/trunk/test/Modules/pr28752.cpp Wed Oct 12 06:57:08 2016
>>> @@ -0,0 +1,19 @@
>>> +// RUN: rm -rf %t
>>> +// RUN: %clang_cc1 -std=c++11 -nostdsysteminc -I%S/Inputs/PR28752 -verify %s
>>> +// RUN: %clang_cc1 -std=c++11 -nostdsysteminc -fmodules -fmodule-map-file=%S/Inputs/PR28752/Subdir1/module.modulemap -fmodule-map-file=%S/Inputs/PR28752/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR28752 -I%S/Inputs/PR28752/Subdir1 -verify %s
>>> +
>>> +#include "a.h"
>>> +#include "Subdir1/c.h"
>>> +#include <vector>
>>> +
>>> +class TClingClassInfo {
>>> +  std::vector<int> fIterStack;
>>> +};
>>> +
>>> +TClingClassInfo *a;
>>> +class TClingBaseClassInfo {
>>> +  TClingBaseClassInfo() { new TClingClassInfo(*a); }
>>> +};
>>> +
>>> +// expected-no-diagnostics
>>> +
>>> 
>>> 
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
> 
> 



More information about the cfe-commits mailing list