r187762 - Started implementing variable templates. Top level declarations should be fully supported, up to some limitations documented as FIXMEs or TODO. Static data member templates work very partially. Static data member templates of class templates need particular attention...

Larisse Voufo lvoufo at google.com
Mon Aug 5 23:26:49 PDT 2013


On Mon, Aug 5, 2013 at 10:39 PM, Nick Lewycky <nlewycky at google.com> wrote:
> On 5 August 2013 18:03, Larisse Voufo <lvoufo at google.com> wrote:
>>
>> Author: lvoufo
>> Date: Mon Aug  5 20:03:05 2013
>> New Revision: 187762
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=187762&view=rev
>> Log:
>> Started implementing variable templates. Top level declarations should be
>> fully supported, up to some limitations documented as FIXMEs or TODO. Static
>> data member templates work very partially. Static data member templates of
>> class templates need particular attention...
>
>
> Nice!!
>

Thanks.

> [...]
>
>>
>> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
>>
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=187762&r1=187761&r2=187762&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
>> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Aug  5 20:03:05 2013
>> @@ -1797,24 +1797,69 @@ Decl *Parser::ParseDeclarationAfterDecla
>>      break;
>>
>>    case ParsedTemplateInfo::Template:
>> -  case ParsedTemplateInfo::ExplicitSpecialization:
>> +  case ParsedTemplateInfo::ExplicitSpecialization: {
>>      ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
>>
>> *TemplateInfo.TemplateParams,
>>                                                 D);
>> -    break;
>>
>> -  case ParsedTemplateInfo::ExplicitInstantiation: {
>> -    DeclResult ThisRes
>> -      = Actions.ActOnExplicitInstantiation(getCurScope(),
>> -                                           TemplateInfo.ExternLoc,
>> -                                           TemplateInfo.TemplateLoc,
>> -                                           D);
>> -    if (ThisRes.isInvalid()) {
>> +    // If this is a forward declaration of a variable template or
>> variable
>> +    // template partial specialization with nested name specifier,
>> complain.
>> +    // FIXME: Move to Sema.
>> +    CXXScopeSpec &SS = D.getCXXScopeSpec();
>> +    if (Tok.is(tok::semi) && ThisDecl && SS.isNotEmpty() &&
>> +        (isa<VarTemplateDecl>(ThisDecl) ||
>> +         isa<VarTemplatePartialSpecializationDecl>(ThisDecl))) {
>> +      Diag(SS.getBeginLoc(), diag::err_forward_var_nested_name_specifier)
>> +          << isa<VarTemplatePartialSpecializationDecl>(ThisDecl)
>> +          << SS.getRange();
>>        SkipUntil(tok::semi, true, true);
>>        return 0;
>>      }
>>
>> -    ThisDecl = ThisRes.get();
>> +    if (VarTemplateDecl *VT =
>> +            ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : 0)
>
>
> You can use dyn_cast_or_null here.

Ok.
>
>>
>> +static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D);
>> +/*
>> +/// \brief Check the new variable specialization against the parsed
>> input.
>> +///
>> +/// FIXME: Model this against function specializations where
>> +/// a new function declaration is checked against the specialization
>> +/// as candidate for redefinition... (?)
>> +static bool CheckVariableTemplateSpecializationType() {
>> +
>> +  if (ExpectedType is undeduced &&  ParsedType is not undeduced)
>> +    ExpectedType = dedudeType();
>> +
>> +  if (both types are undeduced)
>> +    ???;
>> +
>> +  bool CheckType = !ExpectedType()->
>> +
>> +  if (!Context.hasSameType(DI->getType(), ExpectedDI->getType())) {
>> +    unsigned ErrStr = IsPartialSpecialization ? 2 : 1;
>> +    Diag(D.getIdentifierLoc(), diag::err_invalid_var_template_spec_type)
>> +        << ErrStr << VarTemplate << DI->getType() <<
>> ExpectedDI->getType();
>> +    Diag(VarTemplate->getLocation(), diag::note_template_declared_here)
>> +        << 2 << VarTemplate->getDeclName();
>>
>> +    return true;
>> +  }
>> +}
>> +*/
>
>
> Please don't comment commented out or #if 0'd out code.

Noted.

>
>>
>> Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=187762&r1=187761&r2=187762&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Mon Aug  5 20:03:05 2013
>> @@ -2246,7 +2246,7 @@ FinishTemplateArgumentDeduction(Sema &S,
>>  }
>>
>>  /// \brief Perform template argument deduction to determine whether
>> -/// the given template arguments match the given class template
>> +/// the given template arguments match the given variable template
>>  /// partial specialization per C++ [temp.class.spec.match].
>>  Sema::TemplateDeductionResult
>>  Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl
>> *Partial,
>
>
> Hm? This is still about classes not variables.

Ow. Not sure how I missed this, but good catch. Thanks.

>
>>
>> +/// \brief Perform template argument deduction to determine whether
>> +/// the given template arguments match the given variable template
>> +/// partial specialization per C++ [temp.class.spec.match].
>> +/// TODO: Unify with ClassTemplatePartialSpecializationDecl version.
>> +Sema::TemplateDeductionResult
>> +Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl
>> *Partial,
>> +                              const TemplateArgumentList &TemplateArgs,
>> +                              TemplateDeductionInfo &Info) {
>> +  if (Partial->isInvalidDecl())
>> +    return TDK_Invalid;
>> +
>> +  // C++ [temp.class.spec.match]p2:
>> +  //   A partial specialization matches a given actual template
>> +  //   argument list if the template arguments of the partial
>> +  //   specialization can be deduced from the actual template argument
>> +  //   list (14.8.2).
>> +
>> +  // Unevaluated SFINAE context.
>> +  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
>> +  SFINAETrap Trap(*this);
>> +
>> +  SmallVector<DeducedTemplateArgument, 4> Deduced;
>> +  Deduced.resize(Partial->getTemplateParameters()->size());
>> +  if (TemplateDeductionResult Result = ::DeduceTemplateArguments(
>> +          *this, Partial->getTemplateParameters(),
>> Partial->getTemplateArgs(),
>> +          TemplateArgs, Info, Deduced))
>> +    return Result;
>
>
> What's up with the leading :: on the function call?

These are calls to static functions that are only visible in the file.
The scope operator (::) distinguishes them from functions of the same
name in Sema.
The implementations that I adapted these from did the same thing.

>
>> +
>> +  SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
>> Deduced.end());
>> +  InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
>> +                             DeducedArgs, Info);
>> +  if (Inst)
>> +    return TDK_InstantiationDepth;
>> +
>> +  if (Trap.hasErrorOccurred())
>> +    return Sema::TDK_SubstitutionFailure;
>> +
>> +  return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
>> +                                           Deduced, Info);
>
>
> And again here?

Same as above.
>
> Nick
>



More information about the cfe-commits mailing list