From: Richard Smith Date: Sat, 25 Feb 2012 10:20:59 +0000 (+0000) Subject: Fix r151443 to only apply C++11's exception for non-static data member access X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d390de9c6312684c5e5b333f434199e193c7467a;p=clang Fix r151443 to only apply C++11's exception for non-static data member access in cases where we would otherwise disallow the access, and add a -Wc++98-compat diagnostic for this C++11 feature. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151444 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7311756de8..ec4604acec 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3670,6 +3670,9 @@ def err_ref_qualifier_overload : Error< def err_invalid_non_static_member_use : Error< "invalid use of nonstatic data member %0">; +def warn_cxx98_compat_non_static_member_use : Warning< + "use of non-static data member %0 in an unevaluated context is " + "incompatible with C++98">, InGroup, DefaultIgnore; def err_invalid_incomplete_type_use : Error< "invalid use of incomplete type %0">; def err_builtin_func_cast_more_than_one_arg : Error< diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index e90d6e1bc9..e0dfd677aa 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -138,6 +138,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, if (Classes.empty()) return IMA_Static; + bool IsCXX11UnevaluatedField = false; if (SemaRef.getLangOptions().CPlusPlus0x && isField) { // C++11 [expr.prim.general]p12: // An id-expression that denotes a non-static data member or non-static @@ -148,7 +149,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, const Sema::ExpressionEvaluationContextRecord& record = SemaRef.ExprEvalContexts.back(); if (record.Context == Sema::Unevaluated) - return IMA_Field_Uneval_Context; + IsCXX11UnevaluatedField = true; } // If the current context is not an instance method, it can't be @@ -157,7 +158,8 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, if (hasNonInstance) return IMA_Mixed_StaticContext; - return IMA_Error_StaticContext; + return IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context + : IMA_Error_StaticContext; } CXXRecordDecl *contextClass; @@ -176,13 +178,17 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, contextClass->getCanonicalDecl() != R.getNamingClass()->getCanonicalDecl() && contextClass->isProvablyNotDerivedFrom(R.getNamingClass())) - return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); + return hasNonInstance ? IMA_Mixed_Unrelated : + IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context : + IMA_Error_Unrelated; // If we can prove that the current context is unrelated to all the // declaring classes, it can't be an implicit member reference (in // which case it's an error if any of those members are selected). if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) - return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); + return hasNonInstance ? IMA_Mixed_Unrelated : + IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context : + IMA_Error_Unrelated; return (hasNonInstance ? IMA_Mixed : IMA_Instance); } @@ -229,10 +235,13 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, case IMA_Unresolved: return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false); + case IMA_Field_Uneval_Context: + Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) + << R.getLookupNameInfo().getName(); + // Fall through. case IMA_Static: case IMA_Mixed_StaticContext: case IMA_Unresolved_StaticContext: - case IMA_Field_Uneval_Context: if (TemplateArgs || TemplateKWLoc.isValid()) return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); return BuildDeclarationNameExpr(SS, R, false); diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index 879c72211d..12b95765e0 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -1,6 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s +namespace std { struct type_info; } + template // expected-warning {{variadic templates are incompatible with C++98}} class Variadic1 {}; @@ -268,3 +270,12 @@ Later: // expected-note {{possible target of indirect goto}} return; } } + +namespace UnevaluatedMemberAccess { + struct S { + int n; + int f() { return sizeof(S::n); } // ok + }; + int k = sizeof(S::n); // expected-warning {{use of non-static data member 'n' in an unevaluated context is incompatible with C++98}} + const std::type_info &ti = typeid(S::n); // expected-warning {{use of non-static data member 'n' in an unevaluated context is incompatible with C++98}} +}