]> granicus.if.org Git - clang/commitdiff
Fix r151443 to only apply C++11's exception for non-static data member access
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 25 Feb 2012 10:20:59 +0000 (10:20 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 25 Feb 2012 10:20:59 +0000 (10:20 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExprMember.cpp
test/SemaCXX/cxx98-compat.cpp

index 7311756de8e1eec20ac081cf9f74bf18894a66cd..ec4604acec61bbd4acddbfd4efb9a691451513f0 100644 (file)
@@ -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<CXX98Compat>, DefaultIgnore;
 def err_invalid_incomplete_type_use : Error<
   "invalid use of incomplete type %0">;
 def err_builtin_func_cast_more_than_one_arg : Error<
index e90d6e1bc9882968c1cbb7e887db20161f656930..e0dfd677aae8e728a105d3199fafa9626a65ef5c 100644 (file)
@@ -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);
index 879c72211d18761ec7abcc869da5169a1543c920..12b95765e0fa8a7c91aa5553a694de3d2fe54f41 100644 (file)
@@ -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<typename ...T>  // 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}}
+}