From: Douglas Gregor Date: Fri, 5 Feb 2010 19:11:37 +0000 (+0000) Subject: When we're parsing an expression that may have looked like a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ae4c77dc8a77ee89e5b2de8003283249e38075c3;p=clang When we're parsing an expression that may have looked like a declaration, we can end up with template-id annotation tokens for types that have not been converted into type annotation tokens. When this is the case, translate the template-id into a type and parse as an expression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95404 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index c6091367fd..c763c2c6f6 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -22,6 +22,7 @@ #include "clang/Parse/Parser.h" #include "clang/Parse/DeclSpec.h" #include "clang/Parse/Scope.h" +#include "clang/Parse/Template.h" #include "clang/Basic/PrettyStackTrace.h" #include "RAIIObjectsForParser.h" #include "llvm/ADT/SmallVector.h" @@ -806,9 +807,44 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, return ParsePostfixExpressionSuffix(move(Res)); } - case tok::annot_cxxscope: // [C++] id-expression: qualified-id + case tok::annot_cxxscope: { // [C++] id-expression: qualified-id + Token Next = NextToken(); + if (Next.is(tok::annot_template_id)) { + TemplateIdAnnotation *TemplateId + = static_cast(Next.getAnnotationValue()); + if (TemplateId->Kind == TNK_Type_template) { + // We have a qualified template-id that we know refers to a + // type, translate it into a type and continue parsing as a + // cast expression. + CXXScopeSpec SS; + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false); + AnnotateTemplateIdTokenAsType(&SS); + return ParseCastExpression(isUnaryExpression, isAddressOfOperand, + NotCastExpr, TypeOfCast); + } + } + + // Parse as an id-expression. + Res = ParseCXXIdExpression(isAddressOfOperand); + return ParsePostfixExpressionSuffix(move(Res)); + } + + case tok::annot_template_id: { // [C++] template-id + TemplateIdAnnotation *TemplateId + = static_cast(Tok.getAnnotationValue()); + if (TemplateId->Kind == TNK_Type_template) { + // We have a template-id that we know refers to a type, + // translate it into a type and continue parsing as a cast + // expression. + AnnotateTemplateIdTokenAsType(); + return ParseCastExpression(isUnaryExpression, isAddressOfOperand, + NotCastExpr, TypeOfCast); + } + + // Fall through to treat the template-id as an id-expression. + } + case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id - case tok::annot_template_id: // [C++] template-id Res = ParseCXXIdExpression(isAddressOfOperand); return ParsePostfixExpressionSuffix(move(Res)); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 9033137898..2d6bfb433e 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -194,7 +194,9 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, MultiExprArg exprs, SourceLocation *CommaLocs, SourceLocation RParenLoc) { - assert(TypeRep && "Missing type!"); + if (!TypeRep) + return ExprError(); + TypeSourceInfo *TInfo; QualType Ty = GetTypeFromParser(TypeRep, &TInfo); if (!TInfo) diff --git a/test/SemaTemplate/template-id-expr.cpp b/test/SemaTemplate/template-id-expr.cpp index 70a1062c22..b3f41be7bf 100644 --- a/test/SemaTemplate/template-id-expr.cpp +++ b/test/SemaTemplate/template-id-expr.cpp @@ -27,3 +27,20 @@ struct X0 { void test_X0_int(X0 xi, float f) { xi.f2(f); } + +// Not template-id expressions, but they almost look like it. +template +struct Y { + Y(const F&); +}; + +template +struct X { + X(int, int); + void f() { + Y >(X(0, 0)); + Y >(::X(0, 0)); + } +}; + +template struct X<3>;