diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-05-21 23:18:07 +0000 | 
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-05-21 23:18:07 +0000 | 
| commit | 786123dc48d80185f3799ddcaab5703108a64169 (patch) | |
| tree | 4ee4f890e02acf7f6e4996a3f06684a7828b2b5a /clang/lib/Sema/SemaTemplate.cpp | |
| parent | 4dc833c607b516ab7794c9ddbc639a9b9d185cb9 (diff) | |
| download | bcm5719-llvm-786123dc48d80185f3799ddcaab5703108a64169.tar.gz bcm5719-llvm-786123dc48d80185f3799ddcaab5703108a64169.zip | |
Improve parser recovery when we encounter a dependent template name
that is missing the 'template' keyword, e.g., 
  t->getAs<T>()
where getAs is a member of an unknown specialization. C++ requires
that we treat "getAs" as a value, but that would fail to parse since T
is the name of a type. We would then fail at the '>', since a type
cannot be followed by a '>'.
This is a very common error for C++ programmers to make, especially
since GCC occasionally allows it when it shouldn't (as does Visual
C++). So, when we are in this case, we use tentative parsing to see if
the tokens starting at "<" can only be parsed as a template argument
list. If so, we produce a diagnostic with a fix-it that states that
the 'template' keyword is needed:
test/SemaTemplate/dependent-template-recover.cpp:5:8: error: 'template' keyword
      is required to treat 'getAs' as a dependent template name
    t->getAs<T>();
       ^
       template 
This is just a start of this patch; I'd like to apply the same
approach to everywhere that a template-id with dependent template name
can be parsed.
llvm-svn: 104406
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 20 | 
1 files changed, 15 insertions, 5 deletions
| diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 6a4f34731ea..b4f9c3df8b4 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -100,10 +100,12 @@ TemplateNameKind Sema::isTemplateName(Scope *S,                                        UnqualifiedId &Name,                                        TypeTy *ObjectTypePtr,                                        bool EnteringContext, -                                      TemplateTy &TemplateResult) { +                                      TemplateTy &TemplateResult, +                                      bool &MemberOfUnknownSpecialization) {    assert(getLangOptions().CPlusPlus && "No template names in C!");    DeclarationName TName; +  MemberOfUnknownSpecialization = false;    switch (Name.getKind()) {    case UnqualifiedId::IK_Identifier: @@ -128,7 +130,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,    LookupResult R(*this, TName, Name.getSourceRange().getBegin(),                    LookupOrdinaryName);    R.suppressDiagnostics(); -  LookupTemplateName(R, S, SS, ObjectType, EnteringContext); +  LookupTemplateName(R, S, SS, ObjectType, EnteringContext, +                     MemberOfUnknownSpecialization);    if (R.empty() || R.isAmbiguous())      return TNK_Non_template; @@ -191,8 +194,10 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,  void Sema::LookupTemplateName(LookupResult &Found,                                Scope *S, CXXScopeSpec &SS,                                QualType ObjectType, -                              bool EnteringContext) { +                              bool EnteringContext, +                              bool &MemberOfUnknownSpecialization) {    // Determine where to perform name lookup +  MemberOfUnknownSpecialization = false;    DeclContext *LookupCtx = 0;    bool isDependent = false;    if (!ObjectType.isNull()) { @@ -241,6 +246,7 @@ void Sema::LookupTemplateName(LookupResult &Found,    } else if (isDependent) {      // We cannot look into a dependent object type or nested nme      // specifier. +    MemberOfUnknownSpecialization = true;      return;    } else {      // Perform unqualified name lookup in the current scope. @@ -1641,8 +1647,10 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,        RequireCompleteDeclContext(SS, DC))      return BuildDependentDeclRefExpr(SS, Name, NameLoc, &TemplateArgs); +  bool MemberOfUnknownSpecialization;    LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); -  LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false); +  LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false, +                     MemberOfUnknownSpecialization);    if (R.isAmbiguous())      return ExprError(); @@ -1699,8 +1707,10 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,      // "template" keyword is now permitted). We follow the C++0x      // rules, even in C++03 mode, retroactively applying the DR.      TemplateTy Template; +    bool MemberOfUnknownSpecialization;      TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType, -                                          EnteringContext, Template); +                                          EnteringContext, Template, +                                          MemberOfUnknownSpecialization);      if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&          isa<CXXRecordDecl>(LookupCtx) &&          cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) { | 

