[cfe-commits] r106993 - in /cfe/trunk: include/clang/Parse/Action.h lib/Parse/ParseDeclCXX.cpp lib/Sema/Sema.cpp lib/Sema/Sema.h lib/Sema/SemaAccess.cpp test/CXX/temp/temp.spec/temp.explicit/p11.cpp

Chandler Carruth chandlerc at gmail.com
Mon Jun 28 01:39:25 PDT 2010


Author: chandlerc
Date: Mon Jun 28 03:39:25 2010
New Revision: 106993

URL: http://llvm.org/viewvc/llvm-project?rev=106993&view=rev
Log:
Partial fix for PR7267 based on comments by John McCall on an earlier patch.
This is more targeted, as it simply provides toggle actions for the parser to
turn access checking on and off. We then use these to suppress access checking
only while we parse the template-id (included scope specifier) of an explicit
instantiation and explicit specialization of a class template. The
specialization behavior is an extension, as it seems likely a defect that the
standard did not exempt them as it does explicit instantiations.

This allows the very common practice of specializing trait classes to work for
private, internal types. This doesn't address instantiating or specializing
function templates, although those apparently already partially work.

The naming and style for the Action layer isn't my favorite, comments and
suggestions would be appreciated there.

Added:
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p11.cpp
Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaAccess.cpp

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=106993&r1=106992&r2=106993&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Jun 28 03:39:25 2010
@@ -2278,6 +2278,16 @@
     return TypeResult();
   }
 
+  /// \brief Called when the parser begins parsing a construct which should not
+  /// have access control applied to it.
+  virtual void ActOnStartSuppressingAccessChecks() {
+  }
+
+  /// \brief Called when the parser finishes parsing a construct which should
+  /// not have access control applied to it.
+  virtual void ActOnStopSuppressingAccessChecks() {
+  }
+
   //===----------------------- Obj-C Declarations -------------------------===//
 
   // ActOnStartClassInterface - this action is called immediately after parsing

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=106993&r1=106992&r2=106993&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Jun 28 03:39:25 2010
@@ -613,6 +613,20 @@
     ConsumeCodeCompletionToken();
   }
 
+  // C++03 [temp.explicit] 14.7.2/8:
+  //   The usual access checking rules do not apply to names used to specify
+  //   explicit instantiations.
+  //
+  // As an extension we do not perform access checking on the names used to
+  // specify explicit specializations either. This is important to allow
+  // specializing traits classes for private types.
+  bool SuppressingAccessChecks = false;
+  if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
+      TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization) {
+    Actions.ActOnStartSuppressingAccessChecks();
+    SuppressingAccessChecks = true;
+  }
+
   AttributeList *AttrList = 0;
   // If attributes exist after tag, parse them.
   if (Tok.is(tok::kw___attribute))
@@ -732,10 +746,18 @@
       DS.SetTypeSpecError();
       SkipUntil(tok::semi, false, true);
       TemplateId->Destroy();
+      if (SuppressingAccessChecks)
+        Actions.ActOnStopSuppressingAccessChecks();
+
       return;
     }
   }
 
+  // As soon as we're finished parsing the class's template-id, turn access
+  // checking back on.
+  if (SuppressingAccessChecks)
+    Actions.ActOnStopSuppressingAccessChecks();
+
   // There are four options here.  If we have 'struct foo;', then this
   // is either a forward declaration or a friend declaration, which
   // have to be treated differently.  If we have 'struct foo {...' or

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=106993&r1=106992&r2=106993&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Mon Jun 28 03:39:25 2010
@@ -125,8 +125,8 @@
     IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
     GlobalNewDeleteDeclared(false), 
     CompleteTranslationUnit(CompleteTranslationUnit),
-    NumSFINAEErrors(0), NonInstantiationEntries(0), 
-    CurrentInstantiationScope(0), TyposCorrected(0),
+    NumSFINAEErrors(0), SuppressAccessChecking(false),
+    NonInstantiationEntries(0), CurrentInstantiationScope(0), TyposCorrected(0),
     AnalysisWarnings(*this)
 {
   TUScope = 0;

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=106993&r1=106992&r2=106993&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Jun 28 03:39:25 2010
@@ -2797,6 +2797,12 @@
 
   void HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx);
 
+  /// A flag to suppress access checking.
+  bool SuppressAccessChecking;
+
+  void ActOnStartSuppressingAccessChecks();
+  void ActOnStopSuppressingAccessChecks();
+
   enum AbstractDiagSelID {
     AbstractNone = -1,
     AbstractReturnType,

Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=106993&r1=106992&r2=106993&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Mon Jun 28 03:39:25 2010
@@ -1024,6 +1024,9 @@
   if (Entity.getAccess() == AS_public)
     return Sema::AR_accessible;
 
+  if (S.SuppressAccessChecking)
+    return Sema::AR_accessible;
+
   // If we're currently parsing a top-level declaration, delay
   // diagnostics.  This is the only case where parsing a declaration
   // can actually change our effective context for the purposes of
@@ -1334,3 +1337,15 @@
     }
   }
 }
+
+void Sema::ActOnStartSuppressingAccessChecks() {
+  assert(!SuppressAccessChecking &&
+         "Tried to start access check suppression when already started.");
+  SuppressAccessChecking = true;
+}
+
+void Sema::ActOnStopSuppressingAccessChecks() {
+  assert(SuppressAccessChecking &&
+         "Tried to stop access check suprression when already stopped.");
+  SuppressAccessChecking = false;
+}

Added: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p11.cpp?rev=106993&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p11.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p11.cpp Mon Jun 28 03:39:25 2010
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+class X {
+  template <typename T> class Y {};
+};
+
+class A {
+  class B {};
+  class C {};
+};
+
+// C++0x [temp.explicit] 14.7.2/11:
+//   The usual access checking rules do not apply to names used to specify
+//   explicit instantiations.
+template class X::Y<A::B>;
+
+// As an extension, this rule is applied to explicit specializations as well.
+template <> class X::Y<A::C> {};





More information about the cfe-commits mailing list