summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-06-12 23:03:48 +0000
committerReid Kleckner <reid@kleckner.net>2014-06-12 23:03:48 +0000
commit98f39b544ebabb0c964d5fd32650f99d4ae729f8 (patch)
treea03e8d6b8bcd493297a03e2f5c9e6a7fb423ff8c /lib/Sema/SemaExpr.cpp
parent44abf78fbccbd1fc804540f52529aae868e0804b (diff)
downloadclang-98f39b544ebabb0c964d5fd32650f99d4ae729f8.tar.gz
clang-98f39b544ebabb0c964d5fd32650f99d4ae729f8.tar.bz2
clang-98f39b544ebabb0c964d5fd32650f99d4ae729f8.tar.xz
Recover from missing 'typename' in sizeof(T::InnerType)
Summary: 'sizeof' is a UnaryExprOrTypeTrait, and it can contain either a type or an expression. This change threads a RecoveryTSI parameter through the layers between TransformUnaryExprOrTypeTrait the point at which we look up the type. If lookup finds a single type result after instantiation, we now build TypeSourceInfo for it just like a normal transformation would. This fixes the last error in the hello world ATL app that I've been working with, and it now links and runs with clang. Please try it and file bugs! Reviewers: rsmith Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D4108 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210855 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp45
1 files changed, 35 insertions, 10 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7c076f8e84..2ae8b27be9 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2185,7 +2185,8 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
ExprResult
Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
- bool IsAddressOfOperand) {
+ bool IsAddressOfOperand,
+ TypeSourceInfo **RecoveryTSI) {
DeclContext *DC = computeDeclContext(SS, false);
if (!DC)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
@@ -2210,15 +2211,39 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
return ExprError();
}
- if (R.isSingleResult() && R.getAsSingle<TypeDecl>()) {
- // Diagnose a missing typename if this resolved unambiguously to a type in a
- // dependent context.
- // FIXME: Issue a fixit and recover as though the user had written
- // 'typename'.
- Diag(SS.getBeginLoc(), diag::err_typename_missing)
- << SS.getScopeRep() << NameInfo.getName().getAsString()
- << SourceRange(SS.getBeginLoc(), NameInfo.getEndLoc());
- return ExprError();
+ if (const TypeDecl *TD = R.getAsSingle<TypeDecl>()) {
+ // Diagnose a missing typename if this resolved unambiguously to a type in
+ // a dependent context. If we can recover with a type, downgrade this to
+ // a warning in Microsoft compatibility mode.
+ unsigned DiagID = diag::err_typename_missing;
+ if (RecoveryTSI && getLangOpts().MSVCCompat)
+ DiagID = diag::ext_typename_missing;
+ SourceLocation Loc = SS.getBeginLoc();
+ auto D = Diag(Loc, DiagID);
+ D << SS.getScopeRep() << NameInfo.getName().getAsString()
+ << SourceRange(Loc, NameInfo.getEndLoc());
+
+ // Don't recover if the caller isn't expecting us to or if we're in a SFINAE
+ // context.
+ if (!RecoveryTSI)
+ return ExprError();
+
+ // Only issue the fixit if we're prepared to recover.
+ D << FixItHint::CreateInsertion(Loc, "typename ");
+
+ // Recover by pretending this was an elaborated type.
+ QualType Ty = Context.getTypeDeclType(TD);
+ TypeLocBuilder TLB;
+ TLB.pushTypeSpec(Ty).setNameLoc(NameInfo.getLoc());
+
+ QualType ET = getElaboratedType(ETK_None, SS, Ty);
+ ElaboratedTypeLoc QTL = TLB.push<ElaboratedTypeLoc>(ET);
+ QTL.setElaboratedKeywordLoc(SourceLocation());
+ QTL.setQualifierLoc(SS.getWithLocInContext(Context));
+
+ *RecoveryTSI = TLB.getTypeSourceInfo(Context, ET);
+
+ return ExprEmpty();
}
// Defend against this resolving to an implicit member access. We usually