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
This commit is contained in:
Douglas Gregor 2010-02-05 19:11:37 +00:00
Родитель ea48522e97
Коммит ae4c77dc8a
3 изменённых файлов: 58 добавлений и 3 удалений

Просмотреть файл

@ -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<TemplateIdAnnotation *>(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<TemplateIdAnnotation *>(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));

Просмотреть файл

@ -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)

Просмотреть файл

@ -27,3 +27,20 @@ struct X0 {
void test_X0_int(X0<int> xi, float f) {
xi.f2(f);
}
// Not template-id expressions, but they almost look like it.
template<typename F>
struct Y {
Y(const F&);
};
template<int I>
struct X {
X(int, int);
void f() {
Y<X<I> >(X<I>(0, 0));
Y<X<I> >(::X<I>(0, 0));
}
};
template struct X<3>;