r212233 - Fix linkage bug that miscompiled variable templates instantiated from similarly named local types. In essence, this bug ensures that the x<Foo> specialization in function foo() defined as follows differs between two distinct translation units.

Eric Christopher echristo at gmail.com
Wed Jul 2 16:48:34 PDT 2014


On Wed, Jul 2, 2014 at 4:44 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> On Wed, Jul 2, 2014 at 4:25 PM, Eric Christopher <echristo at gmail.com> wrote:
>>
>> It looks like this went out for review but was never reviewed? If so,
>> why did you commit?
>
>
> Agreed, if a patch doesn't meet the "obvious" bar and needs pre-commit
> review, it shouldn't be committed until that review happens. In this case, I
> think the patch actually does meet the "obvious" bar: it's a trivial
> extension of our existing mechanism for other flavors of templates to also
> cover variable templates.
>

Cool. Mostly that if it goes out for review it should stay out for
review until someone acks it.

-eric

> One additional post-commit review comment (in addition to the request for a
> testcase): perhaps it's time to refactor this code to have common code for
> handling any kind of template, rather than having distinct code for each
> different flavor of template.
>
>> On Wed, Jul 2, 2014 at 4:08 PM, Larisse Voufo <lvoufo at google.com> wrote:
>> > Author: lvoufo
>> > Date: Wed Jul  2 18:08:34 2014
>> > New Revision: 212233
>> >
>> > URL: http://llvm.org/viewvc/llvm-project?rev=212233&view=rev
>> > Log:
>> > Fix linkage bug that miscompiled variable templates instantiated from
>> > similarly named local types. In essence, this bug ensures that the x<Foo>
>> > specialization in function foo() defined as follows differs between two
>> > distinct translation units.
>> >     static int &foo() {
>> >        struct Foo { };
>> >        return x<Foo>;
>> >     }
>> >
>> > Modified:
>> >     cfe/trunk/lib/AST/Decl.cpp
>> >
>> > Modified: cfe/trunk/lib/AST/Decl.cpp
>> > URL:
>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=212233&r1=212232&r2=212233&view=diff
>> >
>> > ==============================================================================
>> > --- cfe/trunk/lib/AST/Decl.cpp (original)
>> > +++ cfe/trunk/lib/AST/Decl.cpp Wed Jul  2 18:08:34 2014
>> > @@ -471,6 +471,58 @@ static void mergeTemplateLV(LinkageInfo
>> >    LV.mergeExternalVisibility(argsLV);
>> >  }
>> >
>> > +/// Should we consider visibility associated with the template
>> > +/// arguments and parameters of the given variable template
>> > +/// specialization? As usual, follow class template specialization
>> > +/// logic up to initialization.
>> > +static bool shouldConsiderTemplateVisibility(
>> > +                                 const VarTemplateSpecializationDecl
>> > *spec,
>> > +                                 LVComputationKind computation) {
>> > +  // Include visibility from the template parameters and arguments
>> > +  // only if this is not an explicit instantiation or specialization
>> > +  // with direct explicit visibility (and note that implicit
>> > +  // instantiations won't have a direct attribute).
>> > +  if (!spec->isExplicitInstantiationOrSpecialization())
>> > +    return true;
>> > +
>> > +  // An explicit variable specialization is an independent, top-level
>> > +  // declaration.  As such, if it has an explicit visibility attribute,
>> > +  // that must directly express the user's intent, and we should honor
>> > +  // it.
>> > +  if (spec->isExplicitSpecialization() &&
>> > +      hasExplicitVisibilityAlready(computation))
>> > +    return false;
>> > +
>> > +  return !hasDirectVisibilityAttribute(spec, computation);
>> > +}
>> > +
>> > +/// Merge in template-related linkage and visibility for the given
>> > +/// variable template specialization. As usual, follow class template
>> > +/// specialization logic up to initialization.
>> > +static void mergeTemplateLV(LinkageInfo &LV,
>> > +                            const VarTemplateSpecializationDecl *spec,
>> > +                            LVComputationKind computation) {
>> > +  bool considerVisibility = shouldConsiderTemplateVisibility(spec,
>> > computation);
>> > +
>> > +  // Merge information from the template parameters, but ignore
>> > +  // visibility if we're only considering template arguments.
>> > +
>> > +  VarTemplateDecl *temp = spec->getSpecializedTemplate();
>> > +  LinkageInfo tempLV =
>> > +    getLVForTemplateParameterList(temp->getTemplateParameters(),
>> > computation);
>> > +  LV.mergeMaybeWithVisibility(tempLV,
>> > +           considerVisibility &&
>> > !hasExplicitVisibilityAlready(computation));
>> > +
>> > +  // Merge information from the template arguments.  We ignore
>> > +  // template-argument visibility if we've got an explicit
>> > +  // instantiation with a visibility attribute.
>> > +  const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
>> > +  LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs,
>> > computation);
>> > +  if (considerVisibility)
>> > +    LV.mergeVisibility(argsLV);
>> > +  LV.mergeExternalVisibility(argsLV);
>> > +}
>> > +
>> >  static bool useInlineVisibilityHidden(const NamedDecl *D) {
>> >    // FIXME: we should warn if -fvisibility-inlines-hidden is used with
>> > c.
>> >    const LangOptions &Opts = D->getASTContext().getLangOpts();
>> > @@ -662,6 +714,14 @@ static LinkageInfo getLVForNamespaceScop
>> >      // C99 6.2.2p4 and propagating the visibility attribute, so we
>> > don't have
>> >      // to do it here.
>> >
>> > +    // As per function and class template specializations (below),
>> > +    // consider LV for the template and template arguments.  We're at
>> > file
>> > +    // scope, so we do not need to worry about nested specializations.
>> > +    if (const VarTemplateSpecializationDecl *spec
>> > +              = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
>> > +      mergeTemplateLV(LV, spec, computation);
>> > +    }
>> > +
>> >    //     - a function, unless it has internal linkage; or
>> >    } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
>> > {
>> >      // In theory, we can modify the function's LV by the LV of its
>> > @@ -869,6 +929,10 @@ static LinkageInfo getLVForClassMember(c
>> >
>> >    // Static data members.
>> >    } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
>> > +    if (const VarTemplateSpecializationDecl *spec
>> > +        = dyn_cast<VarTemplateSpecializationDecl>(VD))
>> > +      mergeTemplateLV(LV, spec, computation);
>> > +
>> >      // Modify the variable's linkage by its type, but ignore the
>> >      // type's visibility unless it's a definition.
>> >      LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
>> >
>> >
>> > _______________________________________________
>> > cfe-commits mailing list
>> > cfe-commits at cs.uiuc.edu
>> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>



More information about the cfe-commits mailing list