AST template definition VS. template instantiations

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

AST template definition VS. template instantiations

Benoit Belley
Hi Everyone,

While traversing the Clang AST in a custom static analyzer check (using the RecursiveASTVisitor), I need to determine whether the given function is a template definition because it is part of a template class, template function or a partial specialization of a class template. The reason I need to know this is that template definitions are not fully semantically checked, while template instantiations are. For example, the operator new() referenced by a CXXNewExpr is unresolved in a template definition.

Things are not so clear cut because classes and functions can be nested, and therefore one has to look at all of the enclosing scopes to determine if a given FunctionDecl is actually part of a template.

I have come out with the following function to perform such a check and I am wondering if there is an easier way to achieve this:

// Recursively examines the parent contexts to determine if any of them
// represents either a function or a class template.
static bool isTemplatedContext(DeclContext* ctx)
{
  if ( !ctx ) {
    return false;
  }

  switch ( ctx->getDeclKind() ) {
    case Decl::TranslationUnit:
    case Decl::Namespace:
    case Decl::LinkageSpec:
    case Decl::ClassTemplateSpecialization: {
      // Ignored.
    } break;

    case Decl::CXXRecord: {
      CXXRecordDecl* decl = static_cast<CXXRecordDecl*>(ctx);
      if ( decl->getDescribedClassTemplate() != 0 ) {
        return true;
      }
    } break;

    case Decl::ClassTemplatePartialSpecialization: {
          return true;
    } break;
       
    case Decl::Function:
    case Decl::CXXMethod:
    case Decl::CXXConstructor:
    case Decl::CXXDestructor:
    case Decl::CXXConversion: {
      FunctionDecl* decl = static_cast<FunctionDecl*>(ctx);
      if ( decl->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate ) {
        return true;
      }
    } break;

      default: {
        llvm::errs() << "Unexpected context kind in isTemplatedContext() :" << ctx->getDeclKindName() << "\n";
        assert(false && "Unexpected context kind in isTemplatedContext.\n");
      } break;
  }

  return isTemplatedContext( ctx->getParent() );
}


At first, I thought that it would be simpler to prune the RecursiveASTVisitor to skip any template class definition, but it did not work since members of template classes can be defined outside of the class definition. For example, given:

template <typename T> struct A {
   struct B {
      void foo();
   }
};

template <typename T> void A<T>::B::foo() {}

the DeclContext of the TranslationUnitDecl contains a direct reference to the CXXMethodDecl for foo(). We then have to look at the nested classes to determine that foo() is actually templated.
 
Thanks for your help,
Benoit
 
 
Benoit Belley
Sr Principal Developer
M&E-Product Development Group    
 
Autodesk Canada Inc.
10 Rue Duke
Montreal, Quebec  H3C 2L7
Canada
 
Direct 514 954-7154
 
 


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

image002.gif (892 bytes) Download Attachment
ATT00001..txt (14 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: AST template definition VS. template instantiations

Douglas Gregor

On Aug 25, 2010, at 1:21 PM, Benoit Belley wrote:

> Hi Everyone,
>
> While traversing the Clang AST in a custom static analyzer check (using the RecursiveASTVisitor), I need to determine whether the given function is a template definition because it is part of a template class, template function or a partial specialization of a class template. The reason I need to know this is that template definitions are not fully semantically checked, while template instantiations are. For example, the operator new() referenced by a CXXNewExpr is unresolved in a template definition.

To be super-precise, the operator new() referenced by a CXXNewExpr *might* be unresolved in a template definition. It depends on whether the types and arguments involved are dependent.

> Things are not so clear cut because classes and functions can be nested, and therefore one has to look at all of the enclosing scopes to determine if a given FunctionDecl is actually part of a template.
>
> I have come out with the following function to perform such a check and I am wondering if there is an easier way to achieve this:
>
> // Recursively examines the parent contexts to determine if any of them
> // represents either a function or a class template.
> static bool isTemplatedContext(DeclContext* ctx)
> {
> [snip code]
> }

This is mostly correct, but you don't need it: DeclContext::isDependentContext() does exactly what you need.

        - Doug
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: AST template definition VS. template instantiations

Benoit Belley
Thanks Doug,

Somehow, I missed that function. I was looking for a function with ’Template’ in its name....

Benoit

Le 2010-08-25 à 23:56, Douglas Gregor a écrit :

>
> On Aug 25, 2010, at 1:21 PM, Benoit Belley wrote:
>
>> Hi Everyone,
>>
>> While traversing the Clang AST in a custom static analyzer check (using the RecursiveASTVisitor), I need to determine whether the given function is a template definition because it is part of a template class, template function or a partial specialization of a class template. The reason I need to know this is that template definitions are not fully semantically checked, while template instantiations are. For example, the operator new() referenced by a CXXNewExpr is unresolved in a template definition.
>
> To be super-precise, the operator new() referenced by a CXXNewExpr *might* be unresolved in a template definition. It depends on whether the types and arguments involved are dependent.
>
>> Things are not so clear cut because classes and functions can be nested, and therefore one has to look at all of the enclosing scopes to determine if a given FunctionDecl is actually part of a template.
>>
>> I have come out with the following function to perform such a check and I am wondering if there is an easier way to achieve this:
>>
>> // Recursively examines the parent contexts to determine if any of them
>> // represents either a function or a class template.
>> static bool isTemplatedContext(DeclContext* ctx)
>> {
>> [snip code]
>> }
>
> This is mostly correct, but you don't need it: DeclContext::isDependentContext() does exactly what you need.
>
> - Doug
 
 
Benoit Belley
Sr Principal Developer
M&E-Product Development Group    
 
Autodesk Canada Inc.
10 Rue Duke
Montreal, Quebec  H3C 2L7
Canada
 
Direct 514 954-7154
 
 


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

image002.gif (892 bytes) Download Attachment
ATT00001..txt (14 bytes) Download Attachment