diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-06-12 23:03:48 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-06-12 23:03:48 +0000 |
commit | 98f39b544ebabb0c964d5fd32650f99d4ae729f8 (patch) | |
tree | a03e8d6b8bcd493297a03e2f5c9e6a7fb423ff8c /lib/Sema/SemaExpr.cpp | |
parent | 44abf78fbccbd1fc804540f52529aae868e0804b (diff) | |
download | clang-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.cpp | 45 |
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 |