r284284 - Reinstate r284008 reverted in r284081, with two fixes:

Vassil Vassilev via cfe-commits cfe-commits at lists.llvm.org
Sat Oct 15 00:35:02 PDT 2016


Thanks!

When calling makeMergedDefinitionVisible shouldn't we get the template 
instantiation pattern?
On 14/10/16 23:41, Richard Smith via cfe-commits wrote:
> Author: rsmith
> Date: Fri Oct 14 16:41:24 2016
> New Revision: 284284
>
> URL: http://llvm.org/viewvc/llvm-project?rev=284284&view=rev
> Log:
> Reinstate r284008 reverted in r284081, with two fixes:
>
> 1) Merge and demote variable definitions when we find a redefinition in
> MergeVarDecls, not only when we find one in AddInitializerToDecl (we only reach
> the second case if it's the addition of the initializer itself that converts an
> existing declaration into a definition).
>
> 2) When rebuilding a redeclaration chain for a variable, if we merge two
> definitions together, mark the definitions as merged so the retained definition
> is made visible whenever the demoted definition would have been.
>
> Original commit message (from r283882):
>
> [modules] PR28752: Do not instantiate variable declarations which are not visible.
>
> Original patch by Vassil Vassilev! Changes listed above are mine.
>
> Added:
>      cfe/trunk/test/Modules/Inputs/PR28752/
>        - copied from r284080, cfe/trunk/test/Modules/Inputs/PR28752/
>      cfe/trunk/test/Modules/pr28752.cpp
>        - copied, changed from r284080, cfe/trunk/test/Modules/pr28752.cpp
> Modified:
>      cfe/trunk/include/clang/AST/Decl.h
>      cfe/trunk/include/clang/Sema/Sema.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
>      cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/b.h
>      cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/c.h
>
> Modified: cfe/trunk/include/clang/AST/Decl.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=284284&r1=284283&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Decl.h (original)
> +++ cfe/trunk/include/clang/AST/Decl.h Fri Oct 14 16:41:24 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/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=284284&r1=284283&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Fri Oct 14 16:41:24 2016
> @@ -2286,6 +2286,7 @@ public:
>     void MergeVarDecl(VarDecl *New, LookupResult &Previous);
>     void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld);
>     void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
> +  bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn);
>     bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
>   
>     // AssignmentAction - This is used by all the assignment diagnostic functions
>
> Modified: cfe/trunk/lib/AST/Decl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=284284&r1=284283&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/Decl.cpp (original)
> +++ cfe/trunk/lib/AST/Decl.cpp Fri Oct 14 16:41:24 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=284284&r1=284283&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Oct 14 16:41:24 2016
> @@ -3675,29 +3675,16 @@ void Sema::MergeVarDecl(VarDecl *New, Lo
>     }
>   
>     // C++ doesn't have tentative definitions, so go right ahead and check here.
> -  VarDecl *Def;
>     if (getLangOpts().CPlusPlus &&
> -      New->isThisDeclarationADefinition() == VarDecl::Definition &&
> -      (Def = Old->getDefinition())) {
> -    NamedDecl *Hidden = nullptr;
> -    if (!hasVisibleDefinition(Def, &Hidden) &&
> -        (New->getFormalLinkage() == InternalLinkage ||
> -         New->getDescribedVarTemplate() ||
> -         New->getNumTemplateParameterLists() ||
> -         New->getDeclContext()->isDependentContext())) {
> -      // The previous definition is hidden, and multiple definitions are
> -      // permitted (in separate TUs). Form another definition of it.
> -    } else if (Old->isStaticDataMember() &&
> -               Old->getCanonicalDecl()->isInline() &&
> -               Old->getCanonicalDecl()->isConstexpr()) {
> +      New->isThisDeclarationADefinition() == VarDecl::Definition) {
> +    if (Old->isStaticDataMember() && Old->getCanonicalDecl()->isInline() &&
> +        Old->getCanonicalDecl()->isConstexpr()) {
>         // This definition won't be a definition any more once it's been merged.
>         Diag(New->getLocation(),
>              diag::warn_deprecated_redundant_constexpr_static_def);
> -    } else {
> -      Diag(New->getLocation(), diag::err_redefinition) << New;
> -      Diag(Def->getLocation(), diag::note_previous_definition);
> -      New->setInvalidDecl();
> -      return;
> +    } else if (VarDecl *Def = Old->getDefinition()) {
> +      if (checkVarDeclRedefinition(Def, New))
> +        return;
>       }
>     }
>   
> @@ -3726,6 +3713,32 @@ void Sema::MergeVarDecl(VarDecl *New, Lo
>       New->setImplicitlyInline();
>   }
>   
> +/// We've just determined that \p Old and \p New both appear to be definitions
> +/// of the same variable. Either diagnose or fix the problem.
> +bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) {
> +  if (!hasVisibleDefinition(Old) &&
> +      (New->getFormalLinkage() == InternalLinkage ||
> +       New->isInline() ||
> +       New->getDescribedVarTemplate() ||
> +       New->getNumTemplateParameterLists() ||
> +       New->getDeclContext()->isDependentContext())) {
> +    // The previous definition is hidden, and multiple definitions are
> +    // permitted (in separate TUs). Demote this to a declaration.
> +    New->demoteThisDefinitionToDeclaration();
> +
> +    // Make the canonical definition visible.
> +    if (auto *OldTD = Old->getDescribedVarTemplate())
> +      makeMergedDefinitionVisible(OldTD, New->getLocation());
> +    makeMergedDefinitionVisible(Old, New->getLocation());
> +    return false;
> +  } else {
> +    Diag(New->getLocation(), diag::err_redefinition) << New;
> +    Diag(Old->getLocation(), diag::note_previous_definition);
> +    New->setInvalidDecl();
> +    return true;
> +  }
> +}
> +
>   /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
>   /// no declarator (e.g. "struct foo;") is parsed.
>   Decl *
> @@ -9697,25 +9710,15 @@ void Sema::AddInitializerToDecl(Decl *Re
>         VDecl->setInvalidDecl();
>     }
>   
> +  // If adding the initializer will turn this declaration into a definition,
> +  // and we already have a definition for this variable, diagnose or otherwise
> +  // handle the situation.
>     VarDecl *Def;
>     if ((Def = VDecl->getDefinition()) && Def != VDecl &&
> -      (!VDecl->isStaticDataMember() || VDecl->isOutOfLine())) {
> -    NamedDecl *Hidden = nullptr;
> -    if (!hasVisibleDefinition(Def, &Hidden) &&
> -        (VDecl->getFormalLinkage() == InternalLinkage ||
> -         VDecl->getDescribedVarTemplate() ||
> -         VDecl->getNumTemplateParameterLists() ||
> -         VDecl->getDeclContext()->isDependentContext())) {
> -      // The previous definition is hidden, and multiple definitions are
> -      // permitted (in separate TUs). Form another definition of it.
> -    } else {
> -      Diag(VDecl->getLocation(), diag::err_redefinition)
> -        << VDecl->getDeclName();
> -      Diag(Def->getLocation(), diag::note_previous_definition);
> -      VDecl->setInvalidDecl();
> -      return;
> -    }
> -  }
> +      (!VDecl->isStaticDataMember() || VDecl->isOutOfLine()) &&
> +      !VDecl->isThisDeclarationADemotedDefinition() &&
> +      checkVarDeclRedefinition(Def, VDecl))
> +    return;
>   
>     if (getLangOpts().CPlusPlus) {
>       // C++ [class.static.data]p4
>
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=284284&r1=284283&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Oct 14 16:41:24 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=284284&r1=284283&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Oct 14 16:41:24 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=284284&r1=284283&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Fri Oct 14 16:41:24 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=284284&r1=284283&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Oct 14 16:41:24 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.
> +  // FIXME: Cache the definition once we've found it. Building a chain with
> +  // N definitions currently takes O(N^2) time here.
> +  if (VD->isThisDeclarationADefinition() == VarDecl::Definition) {
> +    for (VarDecl *CurD = PrevVD; CurD; CurD = CurD->getPreviousDecl()) {
> +      if (CurD->isThisDeclarationADefinition() == VarDecl::Definition) {
> +        Reader.mergeDefinitionVisibility(CurD, VD);
> +        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=284284&r1=284283&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Oct 14 16:41:24 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
>
> Modified: 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=284284&r1=284080&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/b.h (original)
> +++ cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/b.h Fri Oct 14 16:41:24 2016
> @@ -1 +1,4 @@
>   #include <vector>
> +
> +template<typename T> struct A { static bool b; };
> +template<typename T> bool A<T>::b;
>
> Modified: 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=284284&r1=284080&r2=284284&view=diff
> ==============================================================================
> --- cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/c.h (original)
> +++ cfe/trunk/test/Modules/Inputs/PR28752/Subdir1/c.h Fri Oct 14 16:41:24 2016
> @@ -0,0 +1,2 @@
> +template<typename T> struct A { static bool b; };
> +template<typename T> bool A<T>::b;
>
> Copied: cfe/trunk/test/Modules/pr28752.cpp (from r284080, cfe/trunk/test/Modules/pr28752.cpp)
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/pr28752.cpp?p2=cfe/trunk/test/Modules/pr28752.cpp&p1=cfe/trunk/test/Modules/pr28752.cpp&r1=284080&r2=284284&rev=284284&view=diff
> ==============================================================================
> --- cfe/trunk/test/Modules/pr28752.cpp (original)
> +++ cfe/trunk/test/Modules/pr28752.cpp Fri Oct 14 16:41:24 2016
> @@ -1,6 +1,6 @@
>   // 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
> +// 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 -fmodules-local-submodule-visibility
>   
>   #include "a.h"
>   #include "Subdir1/c.h"
> @@ -15,5 +15,8 @@ class TClingBaseClassInfo {
>     TClingBaseClassInfo() { new TClingClassInfo(*a); }
>   };
>   
> +namespace { struct Q; }
> +bool *p = &A<Q>::b;
> +
>   // 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