[cfe-commits] r148376 - in /cfe/trunk: lib/Sema/SemaExprMember.cpp test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp

Eli Friedman eli.friedman at gmail.com
Tue Jan 17 19:53:46 PST 2012


Author: efriedma
Date: Tue Jan 17 21:53:45 2012
New Revision: 148376

URL: http://llvm.org/viewvc/llvm-project?rev=148376&view=rev
Log:
Make PotentiallyPotentiallyEvaluated contexts work correctly when referencing a class field from outside an instance method.


Modified:
    cfe/trunk/lib/Sema/SemaExprMember.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp

Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=148376&r1=148375&r2=148376&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprMember.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprMember.cpp Tue Jan 17 21:53:45 2012
@@ -56,7 +56,7 @@
   /// The reference may be an implicit instance member access.
   IMA_Mixed,
 
-  /// The reference may be to an instance member, but it is invalid if
+  /// The reference may be to an instance member, but it might be invalid if
   /// so, because the context is not an instance method.
   IMA_Mixed_StaticContext,
 
@@ -74,6 +74,15 @@
   /// context is not an instance method.
   IMA_Unresolved_StaticContext,
 
+  // The reference is an instance data member access, which is allowed
+  // because we're in C++11 mode and the context is unevaluated.
+  IMA_Field_Uneval_StaticContext,
+
+  // The reference is an instance data member access, which may be allowed
+  // because we're in C++11 mode and the context may be unevaluated
+  // (i.e. the context is PotentiallyPotentiallyEvaluated).
+  IMA_Field_PPE_StaticContext,
+
   /// All possible referrents are instance members and the current
   /// context is not an instance method.
   IMA_Error_StaticContext,
@@ -86,7 +95,7 @@
 /// The given lookup names class member(s) and is not being used for
 /// an address-of-member expression.  Classify the type of access
 /// according to whether it's possible that this reference names an
-/// instance member.  This is best-effort; it is okay to
+/// instance member.  This is best-effort in dependent contexts; it is okay to
 /// conservatively answer "yes", in which case some errors will simply
 /// not be caught until template-instantiation.
 static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
@@ -112,14 +121,14 @@
 
   // Collect all the declaring classes of instance members we find.
   bool hasNonInstance = false;
-  bool hasField = false;
+  bool isField = false;
   llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes;
   for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
     NamedDecl *D = *I;
 
     if (D->isCXXInstanceMember()) {
       if (dyn_cast<FieldDecl>(D))
-        hasField = true;
+        isField = true;
 
       CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
       Classes.insert(R->getCanonicalDecl());
@@ -139,7 +148,7 @@
     if (hasNonInstance)
         return IMA_Mixed_StaticContext;
         
-    if (SemaRef.getLangOptions().CPlusPlus0x && hasField) {
+    if (SemaRef.getLangOptions().CPlusPlus0x && isField) {
       // C++11 [expr.prim.general]p12:
       //   An id-expression that denotes a non-static data member or non-static
       //   member function of a class can only be used:
@@ -148,9 +157,10 @@
       //     appears in an unevaluated operand.
       const Sema::ExpressionEvaluationContextRecord& record
         = SemaRef.ExprEvalContexts.back();
-      bool isUnevaluatedExpression = (record.Context == Sema::Unevaluated);
-      if (isUnevaluatedExpression)
-        return IMA_Mixed_StaticContext;
+      if (record.Context == Sema::Unevaluated)
+        return IMA_Field_Uneval_StaticContext;
+      if (record.Context == Sema::PotentiallyPotentiallyEvaluated)
+        return IMA_Field_PPE_StaticContext;
     }
     
     return IMA_Error_StaticContext;
@@ -186,7 +196,8 @@
 static void DiagnoseInstanceReference(Sema &SemaRef,
                                       const CXXScopeSpec &SS,
                                       NamedDecl *rep,
-                                      const DeclarationNameInfo &nameInfo) {
+                                      const DeclarationNameInfo &nameInfo,
+                                      bool DelayPPEDiag = false) {
   SourceLocation Loc = nameInfo.getLoc();
   SourceRange Range(Loc);
   if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
@@ -195,17 +206,29 @@
     if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) {
       if (MD->isStatic()) {
         // "invalid use of member 'x' in static member function"
-        SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
-        << Range << nameInfo.getName();
+        if (DelayPPEDiag)
+          SemaRef.ExprEvalContexts.back().addDiagnostic(Loc,
+              SemaRef.PDiag(diag::err_invalid_member_use_in_static_method)
+              << Range << nameInfo.getName());
+        else
+          SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
+              << Range << nameInfo.getName();
         return;
       }
     }
-    
-    SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
-    << nameInfo.getName() << Range;
+
+    if (DelayPPEDiag)
+      SemaRef.ExprEvalContexts.back().addDiagnostic(Loc,
+          SemaRef.PDiag(diag::err_invalid_non_static_member_use)
+          << nameInfo.getName() << Range);
+    else
+      SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
+          << nameInfo.getName() << Range;
     return;
   }
-  
+
+  assert(!DelayPPEDiag && "Only need to delay diagnostic for fields");
+
   SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range;
 }
 
@@ -223,9 +246,15 @@
   case IMA_Unresolved:
     return BuildImplicitMemberExpr(SS, R, TemplateArgs, false);
 
+  case IMA_Field_PPE_StaticContext:
+    DiagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),
+                              R.getLookupNameInfo(), /*DelayPPEDiag*/true);
+  // FALL-THROUGH
+
   case IMA_Static:
   case IMA_Mixed_StaticContext:
   case IMA_Unresolved_StaticContext:
+  case IMA_Field_Uneval_StaticContext:
     if (TemplateArgs)
       return BuildTemplateIdExpr(SS, R, false, *TemplateArgs);
     return BuildDeclarationNameExpr(SS, R, false);

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp?rev=148376&r1=148375&r2=148376&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp Tue Jan 17 21:53:45 2012
@@ -19,3 +19,11 @@
     int b[sizeof n]; // ok
   }
 };
+
+// Make sure the rule for unevaluated operands works correctly with typeid.
+namespace std {
+  class type_info;
+}
+class Poly { virtual ~Poly(); };
+const std::type_info& k = typeid(S::m);
+const std::type_info& m = typeid(*(Poly*)S::m); // expected-error {{invalid use of nonstatic data member}}





More information about the cfe-commits mailing list