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 | 32506ed8be375ed3226adea8b507ad260dc3e31d (patch) | |
tree | dd1f31a11de299a3c4fec438f4030acbce5a612d /clang/lib/Sema/SemaExpr.cpp | |
parent | 02ae6902fa42b6914815b1b6371de12cef3677fa (diff) | |
download | bcm5719-llvm-32506ed8be375ed3226adea8b507ad260dc3e31d.tar.gz bcm5719-llvm-32506ed8be375ed3226adea8b507ad260dc3e31d.zip |
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
llvm-svn: 210855
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7c076f8e844..2ae8b27be93 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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 |