r181683 - OpenMP threadprivate with qualified names.

Alexey Bataev a.bataev at hotmail.com
Sun May 12 21:18:18 PDT 2013


Author: abataev
Date: Sun May 12 23:18:18 2013
New Revision: 181683

URL: http://llvm.org/viewvc/llvm-project?rev=181683&view=rev
Log:
OpenMP threadprivate with qualified names.

Modified:
    cfe/trunk/include/clang/AST/DeclOpenMP.h
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/DeclOpenMP.cpp
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/lib/Basic/OpenMPKinds.cpp
    cfe/trunk/lib/Parse/ParseOpenMP.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Parse/RAIIObjectsForParser.h
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/OpenMP/predefined_macro.c
    cfe/trunk/test/OpenMP/threadprivate_messages.cpp

Modified: cfe/trunk/include/clang/AST/DeclOpenMP.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclOpenMP.h?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclOpenMP.h (original)
+++ cfe/trunk/include/clang/AST/DeclOpenMP.h Sun May 12 23:18:18 2013
@@ -1,4 +1,4 @@
-//===--- OpenMP.h - Classes for representing OpenMP directives ---*- C++ -*-===//
+//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 ///
 /// \file
-/// \brief This file defines OpenMP nodes.
+/// \brief This file defines OpenMP nodes for declarative directives.
 ///
 //===----------------------------------------------------------------------===//
 
@@ -20,8 +20,6 @@
 
 namespace clang {
 
-class DeclRefExpr;
-
 /// \brief This represents '#pragma omp threadprivate ...' directive.
 /// For example, in the following, both 'a' and 'A::b' are threadprivate:
 ///
@@ -43,29 +41,29 @@ class OMPThreadPrivateDecl : public Decl
   OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) :
     Decl(DK, DC, L), NumVars(0) { }
 
-  ArrayRef<const DeclRefExpr *> getVars() const {
-    return ArrayRef<const DeclRefExpr *>(
-                   reinterpret_cast<const DeclRefExpr * const *>(this + 1),
+  ArrayRef<const Expr *> getVars() const {
+    return ArrayRef<const Expr *>(
+                   reinterpret_cast<const Expr * const *>(this + 1),
                    NumVars);
   }
 
-  llvm::MutableArrayRef<DeclRefExpr *> getVars() {
-    return llvm::MutableArrayRef<DeclRefExpr *>(
-                                 reinterpret_cast<DeclRefExpr **>(this + 1),
+  llvm::MutableArrayRef<Expr *> getVars() {
+    return llvm::MutableArrayRef<Expr *>(
+                                 reinterpret_cast<Expr **>(this + 1),
                                  NumVars);
   }
 
-  void setVars(ArrayRef<DeclRefExpr *> VL);
+  void setVars(ArrayRef<Expr *> VL);
 
 public:
   static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
                                       SourceLocation L,
-                                      ArrayRef<DeclRefExpr *> VL);
+                                      ArrayRef<Expr *> VL);
   static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
                                                   unsigned ID, unsigned N);
 
-  typedef llvm::MutableArrayRef<DeclRefExpr *>::iterator varlist_iterator;
-  typedef ArrayRef<const DeclRefExpr *>::iterator varlist_const_iterator;
+  typedef llvm::MutableArrayRef<Expr *>::iterator varlist_iterator;
+  typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
 
   unsigned varlist_size() const { return NumVars; }
   bool varlist_empty() const { return NumVars == 0; }

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sun May 12 23:18:18 2013
@@ -819,13 +819,14 @@ def err_seh___finally_block : Error<
 def warn_pragma_omp_ignored : Warning <
   "unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore;
 def warn_omp_extra_tokens_at_eol : Warning <
-  "extra tokens at end of '#pragma omp %0' are ignored">,
+  "extra tokens at the end of '#pragma omp %0' are ignored">,
   InGroup<ExtraTokens>;
 def err_omp_unknown_directive : Error <
   "expected an OpenMP directive">;
 def err_omp_unexpected_directive : Error <
   "unexpected OpenMP directive '#pragma omp %0'">;
-
+def err_omp_expected_var : Error <
+  "expected '#pragma omp %0' argument to be a variable name">;
 } // end of Parse Issue category.
 
 let CategoryName = "Modules Issue" in {

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun May 12 23:18:18 2013
@@ -6336,24 +6336,26 @@ def err_wrong_sampler_addressspace: Erro
   "sampler type cannot be used with the __local and __global address space qualifiers">;
 def err_opencl_global_invalid_addr_space : Error<
   "global variables must have a constant address space qualifier">;
-  
+
+} // end of sema category
+
+let CategoryName = "OpenMP Issue" in {
 // OpenMP support.
 def err_omp_expected_var_arg_suggest : Error<
   "%0 is not a global variable, static local variable or static data member%select{|; did you mean %2?}1">;
 def err_omp_global_var_arg : Error<
   "arguments of '#pragma omp %0' must have %select{global storage|static storage duration}1">;
 def err_omp_ref_type_arg : Error<
-  "arguments of '#pragma omp %0' cannot be of reference type %1">;
+  "arguments of '#pragma omp %0' cannot be of reference type">;
 def err_omp_var_scope : Error<
-  "'#pragma omp %0' must appear in the scope of the %1 variable declaration">;
+  "'#pragma omp %0' must appear in the scope of the %q1 variable declaration">;
 def err_omp_var_used : Error<
-  "'#pragma omp %0' must precede all references to variable %1">;
+  "'#pragma omp %0' must precede all references to variable %q1">;
 def err_omp_var_thread_local : Error<
   "variable %0 cannot be threadprivate because it is thread-local">;
-def err_omp_incomplete_type : Error<
-  "a threadprivate variable must not have incomplete type %0">;
-
-} // end of sema category
+def err_omp_threadprivate_incomplete_type : Error<
+  "threadprivate variable with incomplete type %0">;
+} // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {
 // Objective-C related result type compatibility

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sun May 12 23:18:18 2013
@@ -2138,9 +2138,18 @@ private:
 
   //===--------------------------------------------------------------------===//
   // OpenMP: Directives and clauses.
+  /// \brief Parses declarative OpenMP directives.
   DeclGroupPtrTy ParseOpenMPDeclarativeDirective();
+  /// \brief Parses simple list of variables.
+  ///
+  /// \param Kind Kind of the directive.
+  /// \param [out] VarList List of referenced variables.
+  /// \param AllowScopeSpecifier true, if the variables can have fully
+  /// qualified names.
+  ///
   bool ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
-                                SmallVectorImpl<DeclarationNameInfo> &IdList);
+                                SmallVectorImpl<Expr *> &VarList,
+                                bool AllowScopeSpecifier);
 public:
   bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
                           bool AllowDestructorName,

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sun May 12 23:18:18 2013
@@ -6682,16 +6682,19 @@ public:
                       unsigned SpellingListIndex, bool IsPackExpansion);
 
   // OpenMP directives and clauses.
-
+  /// \brief Called on correct id-expression from the '#pragma omp
+  /// threadprivate'.
+  ExprResult ActOnOpenMPIdExpression(Scope *CurScope,
+                                     CXXScopeSpec &ScopeSpec,
+                                     const DeclarationNameInfo &Id);
   /// \brief Called on well-formed '#pragma omp threadprivate'.
   DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(
-                        SourceLocation Loc,
-                        Scope *CurScope,
-                        ArrayRef<DeclarationNameInfo> IdList);
-  /// \brief Build a new OpenMPThreadPrivateDecl and check its correctness.
+                                     SourceLocation Loc,
+                                     ArrayRef<Expr *> VarList);
+  // \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness.
   OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(
-                        SourceLocation Loc,
-                        ArrayRef<DeclRefExpr *> VarList);
+                                     SourceLocation Loc,
+                                     ArrayRef<Expr *> VarList);
 
   /// \brief The kind of conversion being performed.
   enum CheckedConversionKind {

Modified: cfe/trunk/lib/AST/DeclOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclOpenMP.cpp?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclOpenMP.cpp (original)
+++ cfe/trunk/lib/AST/DeclOpenMP.cpp Sun May 12 23:18:18 2013
@@ -28,9 +28,9 @@ void OMPThreadPrivateDecl::anchor() { }
 OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
                                                    DeclContext *DC,
                                                    SourceLocation L,
-                                                   ArrayRef<DeclRefExpr *> VL) {
+                                                   ArrayRef<Expr *> VL) {
   unsigned Size = sizeof(OMPThreadPrivateDecl) +
-                  (VL.size() * sizeof(DeclRefExpr *));
+                  (VL.size() * sizeof(Expr *));
 
   void *Mem = C.Allocate(Size, llvm::alignOf<OMPThreadPrivateDecl>());
   OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate,
@@ -43,7 +43,7 @@ OMPThreadPrivateDecl *OMPThreadPrivateDe
 OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C,
                                                                unsigned ID,
                                                                unsigned N) {
-  unsigned Size = sizeof(OMPThreadPrivateDecl) + (N * sizeof(DeclRefExpr *));
+  unsigned Size = sizeof(OMPThreadPrivateDecl) + (N * sizeof(Expr *));
 
   void *Mem = AllocateDeserializedDecl(C, ID, Size);
   OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate,
@@ -52,9 +52,9 @@ OMPThreadPrivateDecl *OMPThreadPrivateDe
   return D;
 }
 
-void OMPThreadPrivateDecl::setVars(ArrayRef<DeclRefExpr *> VL) {
+void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) {
   assert(VL.size() == NumVars &&
          "Number of variables is not the same as the preallocated buffer");
-  DeclRefExpr **Vars = reinterpret_cast<DeclRefExpr **>(this + 1);
+  Expr **Vars = reinterpret_cast<Expr **>(this + 1);
   std::copy(VL.begin(), VL.end(), Vars);
 }

Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Sun May 12 23:18:18 2013
@@ -1180,9 +1180,9 @@ void DeclPrinter::VisitOMPThreadPrivateD
   if (!D->varlist_empty()) {
     for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
                                                 E = D->varlist_end();
-         I != E; ++I) {
+                                                I != E; ++I) {
       Out << (I == D->varlist_begin() ? '(' : ',')
-          << *cast<NamedDecl>((*I)->getDecl());
+          << *cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
     }
     Out << ")";
   }

Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original)
+++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Sun May 12 23:18:18 2013
@@ -32,7 +32,7 @@ const char *clang::getOpenMPDirectiveNam
   assert(Kind < NUM_OPENMP_DIRECTIVES);
   switch (Kind) {
   case OMPD_unknown:
-    return ("unknown");
+    return "unknown";
 #define OPENMP_DIRECTIVE(Name) \
   case OMPD_##Name : return #Name;
 #include "clang/Basic/OpenMPKinds.def"
@@ -41,3 +41,4 @@ const char *clang::getOpenMPDirectiveNam
   }
   llvm_unreachable("Invalid OpenMP directive kind");
 }
+

Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Sun May 12 23:18:18 2013
@@ -12,8 +12,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTConsumer.h"
-#include "clang/Parse/Parser.h"
 #include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/Scope.h"
+#include "llvm/ADT/PointerIntPair.h"
 #include "RAIIObjectsForParser.h"
 using namespace clang;
 
@@ -21,22 +23,24 @@ using namespace clang;
 // OpenMP declarative directives.
 //===----------------------------------------------------------------------===//
 
-/// \brief Parses OpenMP declarative directive
-///       threadprivate-directive
-///         annot_pragma_openmp threadprivate simple-variable-list
+/// \brief Parsing of declarative OpenMP directives.
+///
+///       threadprivate-directive:
+///         annot_pragma_openmp 'threadprivate' simple-variable-list
 ///
 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
 
   SourceLocation Loc = ConsumeToken();
-  SmallVector<DeclarationNameInfo, 5> Identifiers;
-  OpenMPDirectiveKind Kind = Tok.isAnnotation() ?
-                                 OMPD_unknown :
-                                 getOpenMPDirectiveKind(PP.getSpelling(Tok));
-  switch(Kind) {
+  SmallVector<Expr *, 5> Identifiers;
+  OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
+                                  OMPD_unknown :
+                                  getOpenMPDirectiveKind(PP.getSpelling(Tok));
+
+  switch (DKind) {
   case OMPD_threadprivate:
     ConsumeToken();
-    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers)) {
+    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
       // The last seen token is annot_pragma_openmp_end - need to check for
       // extra tokens.
       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
@@ -44,9 +48,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpen
           << getOpenMPDirectiveName(OMPD_threadprivate);
         SkipUntil(tok::annot_pragma_openmp_end, false, true);
       }
+      // Skip the last annot_pragma_openmp_end.
       ConsumeToken();
       return Actions.ActOnOpenMPThreadprivateDirective(Loc,
-                                                       getCurScope(),
                                                        Identifiers);
     }
     break;
@@ -55,7 +59,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpen
     break;
   default:
     Diag(Tok, diag::err_omp_unexpected_directive)
-      << getOpenMPDirectiveName(Kind);
+      << getOpenMPDirectiveName(DKind);
     break;
   }
   SkipUntil(tok::annot_pragma_openmp_end, false);
@@ -63,56 +67,69 @@ Parser::DeclGroupPtrTy Parser::ParseOpen
 }
 
 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
-/// directive
-/// simple-variable-list:
-///   ( unqualified-id {, unqualified-id} ) annot_pragma_openmp_end
+/// directive.
+///
+///   simple-variable-list:
+///         '(' id-expression {, id-expression} ')'
 ///
-bool Parser::ParseOpenMPSimpleVarList(
-  OpenMPDirectiveKind Kind,
-  SmallVectorImpl<DeclarationNameInfo> &IdList) {
+bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
+                                      SmallVectorImpl<Expr *> &VarList,
+                                      bool AllowScopeSpecifier) {
+  VarList.clear();
   // Parse '('.
-  bool IsCorrect = true;
-  BalancedDelimiterTracker T(*this, tok::l_paren);
-  if (T.expectAndConsume(diag::err_expected_lparen_after,
-                         getOpenMPDirectiveName(Kind))) {
-    SkipUntil(tok::annot_pragma_openmp_end, false, true);
-    return false;
-  }
+  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+  bool LParen = !T.expectAndConsume(diag::err_expected_lparen_after,
+                                    getOpenMPDirectiveName(Kind));
+  bool IsCorrect = LParen;
+  bool NoIdentIsFound = true;
 
   // Read tokens while ')' or annot_pragma_openmp_end is not found.
-  do {
+  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
     CXXScopeSpec SS;
     SourceLocation TemplateKWLoc;
     UnqualifiedId Name;
     // Read var name.
     Token PrevTok = Tok;
+    NoIdentIsFound = false;
 
-    if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
-                           TemplateKWLoc, Name)) {
+    if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
+        ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
       IsCorrect = false;
       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                 false, true);
-    }
-    else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
-             Tok.isNot(tok::annot_pragma_openmp_end)) {
+    } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
+                                  TemplateKWLoc, Name)) {
+      IsCorrect = false;
+      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+                false, true);
+    } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
+               Tok.isNot(tok::annot_pragma_openmp_end)) {
       IsCorrect = false;
       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                 false, true);
-      Diag(PrevTok.getLocation(), diag::err_expected_unqualified_id)
-        << getLangOpts().CPlusPlus
+      Diag(PrevTok.getLocation(), diag::err_expected_ident)
         << SourceRange(PrevTok.getLocation(), PrevTokLocation);
     } else {
-      IdList.push_back(Actions.GetNameFromUnqualifiedId(Name));
+      DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
+      ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
+                                                       NameInfo);
+      if (Res.isUsable())
+        VarList.push_back(Res.take());
     }
     // Consume ','.
     if (Tok.is(tok::comma)) {
       ConsumeToken();
     }
-  } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
+  }
 
-  if (IsCorrect || Tok.is(tok::r_paren)) {
-    IsCorrect = !T.consumeClose() && IsCorrect;
+  if (NoIdentIsFound) {
+    Diag(Tok, diag::err_expected_ident);
+    IsCorrect = false;
   }
 
-  return !IsCorrect && IdList.empty();
+  // Parse ')'.
+  IsCorrect = ((LParen || Tok.is(tok::r_paren)) && !T.consumeClose())
+              && IsCorrect;
+
+  return !IsCorrect && VarList.empty();
 }

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Sun May 12 23:18:18 2013
@@ -1897,7 +1897,7 @@ bool BalancedDelimiterTracker::diagnoseO
   P.Diag(P.Tok, diag::err_bracket_depth_exceeded)
     << P.getLangOpts().BracketDepth;
   P.Diag(P.Tok, diag::note_bracket_depth);
-  P.SkipUntil(tok::eof);
+  P.SkipUntil(tok::eof, FinalToken);
   return true;  
 }
 
@@ -1927,7 +1927,8 @@ bool BalancedDelimiterTracker::diagnoseM
   }
   P.Diag(P.Tok, DID);
   P.Diag(LOpen, diag::note_matching) << LHSName;
-  if (P.SkipUntil(Close, /*StopAtSemi*/ true, /*DontConsume*/ true))
+  if (P.SkipUntil(Close, FinalToken, /*StopAtSemi*/ true, /*DontConsume*/ true)
+      && P.Tok.is(Close))
     LClose = P.ConsumeAnyToken();
   return true;
 }

Modified: cfe/trunk/lib/Parse/RAIIObjectsForParser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/RAIIObjectsForParser.h?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/RAIIObjectsForParser.h (original)
+++ cfe/trunk/lib/Parse/RAIIObjectsForParser.h Sun May 12 23:18:18 2013
@@ -358,7 +358,7 @@ namespace clang {
   /// pair, such as braces { ... } or parentheses ( ... ).
   class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
     Parser& P;
-    tok::TokenKind Kind, Close;
+    tok::TokenKind Kind, Close, FinalToken;
     SourceLocation (Parser::*Consumer)();
     SourceLocation LOpen, LClose;
     
@@ -377,9 +377,10 @@ namespace clang {
     bool diagnoseMissingClose();
     
   public:
-    BalancedDelimiterTracker(Parser& p, tok::TokenKind k)
+    BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
+                             tok::TokenKind FinalToken = tok::semi)
       : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
-        P(p), Kind(k)
+        P(p), Kind(k), FinalToken(FinalToken)
     {
       switch (Kind) {
         default: llvm_unreachable("Unexpected balanced token");

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Sun May 12 23:18:18 2013
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 /// \file
 /// \brief This file implements semantic analysis for OpenMP directives and
-/// clauses
+/// clauses.
 ///
 //===----------------------------------------------------------------------===//
 
@@ -22,117 +22,121 @@ using namespace clang;
 
 namespace {
 
-  class VarDeclFilterCCC : public CorrectionCandidateCallback {
-    private:
-      Sema &Actions;
-    public:
-      VarDeclFilterCCC(Sema &S) : Actions(S) { }
-      virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
-        NamedDecl *ND = Candidate.getCorrectionDecl();
-        if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
-          return VD->hasGlobalStorage() &&
-                 Actions.isDeclInScope(ND, Actions.getCurLexicalContext(),
-                                       Actions.getCurScope());
-        }
-        return false;
-      }
-  };
+class VarDeclFilterCCC : public CorrectionCandidateCallback {
+private:
+  Sema &Actions;
+public:
+  VarDeclFilterCCC(Sema &S) : Actions(S) { }
+  virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
+    NamedDecl *ND = Candidate.getCorrectionDecl();
+    if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
+      return VD->hasGlobalStorage() &&
+             Actions.isDeclInScope(ND, Actions.getCurLexicalContext(),
+                                   Actions.getCurScope());
+    }
+    return false;
+  }
+};
 }
-Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
-                              SourceLocation Loc,
-                              Scope *CurScope,
-                              ArrayRef<DeclarationNameInfo> IdList) {
-  SmallVector<DeclRefExpr *, 5> Vars;
-  for (ArrayRef<DeclarationNameInfo>::iterator I = IdList.begin(),
-                                               E = IdList.end();
-       I != E; ++I) {
-    LookupResult Lookup(*this, *I, LookupOrdinaryName);
-    LookupParsedName(Lookup, CurScope, NULL, true);
-
-    if (Lookup.isAmbiguous())
-      continue;
 
-    VarDecl *VD;
-    if (!Lookup.isSingleResult()) {
-      VarDeclFilterCCC Validator(*this);
-      TypoCorrection Corrected = CorrectTypo(*I, LookupOrdinaryName, CurScope,
-                                             0, Validator);
-      std::string CorrectedStr = Corrected.getAsString(getLangOpts());
-      std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
-      if (Lookup.empty()) {
-        if (Corrected.isResolved()) {
-          Diag(I->getLoc(), diag::err_undeclared_var_use_suggest)
-            << I->getName() << CorrectedQuotedStr
-            << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
-        } else {
-          Diag(I->getLoc(), diag::err_undeclared_var_use)
-            << I->getName();
-        }
+ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
+                                         CXXScopeSpec &ScopeSpec,
+                                         const DeclarationNameInfo &Id) {
+  LookupResult Lookup(*this, Id, LookupOrdinaryName);
+  LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
+
+  if (Lookup.isAmbiguous())
+    return ExprError();
+
+  VarDecl *VD;
+  if (!Lookup.isSingleResult()) {
+    VarDeclFilterCCC Validator(*this);
+    TypoCorrection Corrected = CorrectTypo(Id, LookupOrdinaryName, CurScope,
+                                           0, Validator);
+    std::string CorrectedStr = Corrected.getAsString(getLangOpts());
+    std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
+    if (Lookup.empty()) {
+      if (Corrected.isResolved()) {
+        Diag(Id.getLoc(), diag::err_undeclared_var_use_suggest)
+          << Id.getName() << CorrectedQuotedStr
+          << FixItHint::CreateReplacement(Id.getLoc(), CorrectedStr);
       } else {
-        Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
-          << I->getName() << Corrected.isResolved() << CorrectedQuotedStr
-          << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
+        Diag(Id.getLoc(), diag::err_undeclared_var_use)
+          << Id.getName();
       }
-      if (!Corrected.isResolved()) continue;
-      VD = Corrected.getCorrectionDeclAs<VarDecl>();
     } else {
-      if (!(VD = Lookup.getAsSingle<VarDecl>())) {
-        Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
-          << I->getName() << 0;
-        Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
-        continue;
-      }
-    }
-
-    // OpenMP [2.9.2, Syntax, C/C++]
-    //   Variables must be file-scope, namespace-scope, or static block-scope.
-    if (!VD->hasGlobalStorage()) {
-      Diag(I->getLoc(), diag::err_omp_global_var_arg)
-        << getOpenMPDirectiveName(OMPD_threadprivate)
-        << !VD->isStaticLocal();
-      Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
-      continue;
+      Diag(Id.getLoc(), diag::err_omp_expected_var_arg_suggest)
+        << Id.getName() << Corrected.isResolved() << CorrectedQuotedStr
+        << FixItHint::CreateReplacement(Id.getLoc(), CorrectedStr);
+    }
+    if (!Corrected.isResolved()) return ExprError();
+    VD = Corrected.getCorrectionDeclAs<VarDecl>();
+  } else {
+    if (!(VD = Lookup.getAsSingle<VarDecl>())) {
+      Diag(Id.getLoc(), diag::err_omp_expected_var_arg_suggest)
+        << Id.getName() << 0;
+      Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
+      return ExprError();
     }
+  }
+  Lookup.suppressDiagnostics();
 
-    // OpenMP [2.9.2, Restrictions, C/C++, p.2]
-    //   A threadprivate directive for file-scope variables must appear outside
-    //   any definition or declaration.
-    // OpenMP [2.9.2, Restrictions, C/C++, p.3]
-    //   A threadprivate directive for static class member variables must appear
-    //   in the class definition, in the same scope in which the member
-    //   variables are declared.
-    // OpenMP [2.9.2, Restrictions, C/C++, p.4]
-    //   A threadprivate directive for namespace-scope variables must appear
-    //   outside any definition or declaration other than the namespace
-    //   definition itself.
-    // OpenMP [2.9.2, Restrictions, C/C++, p.6]
-    //   A threadprivate directive for static block-scope variables must appear
-    //   in the scope of the variable and not in a nested scope.
-    NamedDecl *ND = cast<NamedDecl>(VD);
-    if (!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
-      Diag(I->getLoc(), diag::err_omp_var_scope)
-        << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
-      Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
-      continue;
-    }
+  // OpenMP [2.9.2, Syntax, C/C++]
+  //   Variables must be file-scope, namespace-scope, or static block-scope.
+  if (!VD->hasGlobalStorage()) {
+    Diag(Id.getLoc(), diag::err_omp_global_var_arg)
+      << getOpenMPDirectiveName(OMPD_threadprivate)
+      << !VD->isStaticLocal();
+    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+                  VarDecl::DeclarationOnly;
+    Diag(VD->getLocation(),
+         IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD;
+    return ExprError();
+  }
 
-    // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
-    //   A threadprivate directive must lexically precede all references to any
-    //   of the variables in its list.
-    if (VD->isUsed()) {
-      Diag(I->getLoc(), diag::err_omp_var_used)
-        << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
-      continue;
-    }
+  // OpenMP [2.9.2, Restrictions, C/C++, p.2]
+  //   A threadprivate directive for file-scope variables must appear outside
+  //   any definition or declaration.
+  // OpenMP [2.9.2, Restrictions, C/C++, p.3]
+  //   A threadprivate directive for static class member variables must appear
+  //   in the class definition, in the same scope in which the member
+  //   variables are declared.
+  // OpenMP [2.9.2, Restrictions, C/C++, p.4]
+  //   A threadprivate directive for namespace-scope variables must appear
+  //   outside any definition or declaration other than the namespace
+  //   definition itself.
+  // OpenMP [2.9.2, Restrictions, C/C++, p.6]
+  //   A threadprivate directive for static block-scope variables must appear
+  //   in the scope of the variable and not in a nested scope.
+  NamedDecl *ND = cast<NamedDecl>(VD);
+  if (!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
+    Diag(Id.getLoc(), diag::err_omp_var_scope)
+      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+                  VarDecl::DeclarationOnly;
+    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+                                     diag::note_defined_here) << VD;
+    return ExprError();
+  }
 
-    QualType ExprType = VD->getType().getNonReferenceType();
-    DeclRefExpr *Var = cast<DeclRefExpr>(BuildDeclRefExpr(VD,
-                                                          ExprType,
-                                                          VK_RValue,
-                                                          I->getLoc()).take());
-    Vars.push_back(Var);
+  // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
+  //   A threadprivate directive must lexically precede all references to any
+  //   of the variables in its list.
+  if (VD->isUsed()) {
+    Diag(Id.getLoc(), diag::err_omp_var_used)
+      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+    return ExprError();
   }
-  if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, Vars)) {
+
+  QualType ExprType = VD->getType().getNonReferenceType();
+  ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_RValue, Id.getLoc());
+  return DE;
+}
+
+Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
+                                SourceLocation Loc,
+                                ArrayRef<Expr *> VarList) {
+  if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
     CurContext->addDecl(D);
     return DeclGroupPtrTy::make(DeclGroupRef(D));
   }
@@ -141,18 +145,19 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPTh
 
 OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
                                  SourceLocation Loc,
-                                 ArrayRef<DeclRefExpr *> VarList) {
-  SmallVector<DeclRefExpr *, 5> Vars;
-  for (ArrayRef<DeclRefExpr *>::iterator I = VarList.begin(),
+                                 ArrayRef<Expr *> VarList) {
+  SmallVector<Expr *, 8> Vars;
+  for (ArrayRef<Expr *>::iterator I = VarList.begin(),
                                          E = VarList.end();
        I != E; ++I) {
-    VarDecl *VD = cast<VarDecl>((*I)->getDecl());
-    SourceLocation ILoc = (*I)->getLocation();
+    DeclRefExpr *DE = cast<DeclRefExpr>(*I);
+    VarDecl *VD = cast<VarDecl>(DE->getDecl());
+    SourceLocation ILoc = DE->getExprLoc();
 
     // OpenMP [2.9.2, Restrictions, C/C++, p.10]
     //   A threadprivate variable must not have an incomplete type.
     if (RequireCompleteType(ILoc, VD->getType(),
-                            diag::err_omp_incomplete_type)) {
+                            diag::err_omp_threadprivate_incomplete_type)) {
       continue;
     }
 
@@ -160,15 +165,21 @@ OMPThreadPrivateDecl *Sema::CheckOMPThre
     //   A threadprivate variable must not have a reference type.
     if (VD->getType()->isReferenceType()) {
       Diag(ILoc, diag::err_omp_ref_type_arg)
-        << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
-      Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+        << getOpenMPDirectiveName(OMPD_threadprivate);
+      bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+                    VarDecl::DeclarationOnly;
+      Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+                                       diag::note_defined_here) << VD;
       continue;
     }
 
     // Check if this is a TLS variable.
     if (VD->getTLSKind()) {
       Diag(ILoc, diag::err_omp_var_thread_local) << VD;
-      Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+      bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+                    VarDecl::DeclarationOnly;
+      Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+                                       diag::note_defined_here) << VD;
       continue;
     }
 
@@ -179,3 +190,4 @@ OMPThreadPrivateDecl *Sema::CheckOMPThre
                                                getCurLexicalContext(),
                                                Loc, Vars);
 }
+

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun May 12 23:18:18 2013
@@ -2231,13 +2231,13 @@ Decl *TemplateDeclInstantiator::VisitCla
 
 Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
                                      OMPThreadPrivateDecl *D) {
-  SmallVector<DeclRefExpr *, 5> Vars;
-  for (ArrayRef<DeclRefExpr *>::iterator I = D->varlist_begin(),
-                                         E = D->varlist_end();
+  SmallVector<Expr *, 5> Vars;
+  for (ArrayRef<Expr *>::iterator I = D->varlist_begin(),
+                                  E = D->varlist_end();
        I != E; ++I) {
     Expr *Var = SemaRef.SubstExpr(*I, TemplateArgs).take();
     assert(isa<DeclRefExpr>(Var) && "threadprivate arg is not a DeclRefExpr");
-    Vars.push_back(cast<DeclRefExpr>(Var));
+    Vars.push_back(Var);
   }
 
   OMPThreadPrivateDecl *TD =

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sun May 12 23:18:18 2013
@@ -1644,10 +1644,10 @@ void ASTDeclReader::mergeRedeclarable(Re
 void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
   VisitDecl(D);
   unsigned NumVars = D->varlist_size();
-  SmallVector<DeclRefExpr *, 16> Vars;
+  SmallVector<Expr *, 16> Vars;
   Vars.reserve(NumVars);
   for (unsigned i = 0; i != NumVars; ++i) {
-    Vars.push_back(cast<DeclRefExpr>(Reader.ReadExpr(F)));
+    Vars.push_back(Reader.ReadExpr(F));
   }
   D->setVars(Vars);
 }

Modified: cfe/trunk/test/OpenMP/predefined_macro.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/predefined_macro.c?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/predefined_macro.c (original)
+++ cfe/trunk/test/OpenMP/predefined_macro.c Sun May 12 23:18:18 2013
@@ -31,4 +31,3 @@
 #error "_OPENMP macro is defined without -fopenmp option"
 #endif // _OPENMP
 #endif // FOPENMP
-

Modified: cfe/trunk/test/OpenMP/threadprivate_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/threadprivate_messages.cpp?rev=181683&r1=181682&r2=181683&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/threadprivate_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/threadprivate_messages.cpp Sun May 12 23:18:18 2013
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 %s
 
-#pragma omp threadprivate // expected-error {{expected '(' after 'threadprivate'}}
-#pragma omp threadprivate( // expected-error {{expected unqualified-id}}
-#pragma omp threadprivate() // expected-error {{expected unqualified-id}}
+#pragma omp threadprivate // expected-error {{expected '(' after 'threadprivate'}} expected-error {{expected identifier}}
+#pragma omp threadprivate( // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp threadprivate() // expected-error {{expected identifier}}
 #pragma omp threadprivate(1) // expected-error {{expected unqualified-id}}
 struct CompleteSt{
  int a;
@@ -11,27 +11,27 @@ struct CompleteSt{
 struct CompleteSt1{
 #pragma omp threadprivate(1) // expected-error {{expected unqualified-id}}
  int a;
-} d; // expected-note {{forward declaration of 'd'}}
+} d; // expected-note {{'d' defined here}}
 
-int a; // expected-note {{forward declaration of 'a'}}
+int a; // expected-note {{'a' defined here}}
 
 #pragma omp threadprivate(a)
 #pragma omp threadprivate(u) // expected-error {{use of undeclared identifier 'u'}}
 #pragma omp threadprivate(d, a) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'a'}}
 int foo() { // expected-note {{declared here}}
   static int l;
-#pragma omp threadprivate(l)) // expected-warning {{extra tokens at end of '#pragma omp threadprivate' are ignored}}
+#pragma omp threadprivate(l)) // expected-warning {{extra tokens at the end of '#pragma omp threadprivate' are ignored}}
   return (a);
 }
 
-#pragma omp threadprivate a // expected-error {{expected '(' after 'threadprivate'}}
+#pragma omp threadprivate a // expected-error {{expected '(' after 'threadprivate'}} expected-error {{'#pragma omp threadprivate' must precede all references to variable 'a'}}
 #pragma omp threadprivate(d // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{'#pragma omp threadprivate' must precede all references to variable 'd'}}
-#pragma omp threadprivate(d))
+#pragma omp threadprivate(d)) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'd'}} expected-warning {{extra tokens at the end of '#pragma omp threadprivate' are ignored}}
 int x, y;
-#pragma omp threadprivate(x)) // expected-warning {{extra tokens at end of '#pragma omp threadprivate' are ignored}}
-#pragma omp threadprivate(y)), // expected-warning {{extra tokens at end of '#pragma omp threadprivate' are ignored}}
+#pragma omp threadprivate(x)) // expected-warning {{extra tokens at the end of '#pragma omp threadprivate' are ignored}}
+#pragma omp threadprivate(y)), // expected-warning {{extra tokens at the end of '#pragma omp threadprivate' are ignored}}
 #pragma omp threadprivate(a,d)  // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'a'}} expected-error {{'#pragma omp threadprivate' must precede all references to variable 'd'}}
-#pragma omp threadprivate(d.a) // expected-error {{expected unqualified-id}}
+#pragma omp threadprivate(d.a) // expected-error {{expected identifier}}
 #pragma omp threadprivate((float)a) // expected-error {{expected unqualified-id}}
 int foa;
 #pragma omp threadprivate(faa) // expected-error {{use of undeclared identifier 'faa'; did you mean 'foa'?}}
@@ -41,31 +41,31 @@ int foa;
 struct IncompleteSt; // expected-note {{forward declaration of 'IncompleteSt'}}
 
 extern IncompleteSt e;
-#pragma omp threadprivate (e) // expected-error {{a threadprivate variable must not have incomplete type 'IncompleteSt'}}
+#pragma omp threadprivate (e) // expected-error {{threadprivate variable with incomplete type 'IncompleteSt'}}
 
-int &f = a; // expected-note {{forward declaration of 'f'}}
-#pragma omp threadprivate (f) // expected-error {{arguments of '#pragma omp threadprivate' cannot be of reference type 'int &'}}
+int &f = a; // expected-note {{'f' defined here}}
+#pragma omp threadprivate (f) // expected-error {{arguments of '#pragma omp threadprivate' cannot be of reference type}}
 
 class Class {
   private:
     int a; // expected-note {{declared here}}
-    static int b;
+    static int b; // expected-note {{'b' declared here}}
     Class() : a(0){}
   public:
     Class (int aaa) : a(aaa) {}
 #pragma omp threadprivate (b, a) // expected-error {{'a' is not a global variable, static local variable or static data member}}
 } g(10);
 #pragma omp threadprivate (b) // expected-error {{use of undeclared identifier 'b'}}
-#pragma omp threadprivate (Class::b) // expected-error {{expected unqualified-id}}
+#pragma omp threadprivate (Class::b) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'Class::b' variable declaration}}
 #pragma omp threadprivate (g)
 
 namespace ns {
-  int m;
+  int m; // expected-note 2 {{'m' defined here}}
 #pragma omp threadprivate (m)
 }
 #pragma omp threadprivate (m) // expected-error {{use of undeclared identifier 'm'}}
-#pragma omp threadprivate (ns::m) // expected-error {{expected unqualified-id}}
-#pragma omp threadprivate (ns:m) // expected-error {{expected unqualified-id}}
+#pragma omp threadprivate (ns::m) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'ns::m' variable declaration}}
+#pragma omp threadprivate (ns:m) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}} expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'ns::m' variable declaration}}
 
 const int h = 12;
 const volatile int i = 10;
@@ -84,26 +84,30 @@ class TempClass {
 };
 #pragma omp threadprivate (s) // expected-error {{use of undeclared identifier 's'}}
 
-static __thread int t; // expected-note {{forward declaration of 't'}}
+static __thread int t; // expected-note {{'t' defined here}}
 #pragma omp threadprivate (t) // expected-error {{variable 't' cannot be threadprivate because it is thread-local}}
 
 int o; // expected-note {{candidate found by name lookup is 'o'}}
+#pragma omp threadprivate (o)
 namespace {
 int o; // expected-note {{candidate found by name lookup is '<anonymous namespace>::o'}}
+#pragma omp threadprivate (o)
+#pragma omp threadprivate (o) // expected-error {{'#pragma omp threadprivate' must precede all references to variable '<anonymous namespace>::o'}}
 }
 #pragma omp threadprivate (o) // expected-error {{reference to 'o' is ambiguous}}
+#pragma omp threadprivate (::o) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'o'}}
 
-int main(int argc, char **argv) { // expected-note {{forward declaration of 'argc'}}
+int main(int argc, char **argv) { // expected-note {{'argc' defined here}}
 
-  int x, y = argc; // expected-note {{forward declaration of 'y'}}
+  int x, y = argc; // expected-note {{'y' defined here}}
   static double d1;
   static double d2;
-  static double d3; // expected-note {{forward declaration of 'd3'}}
+  static double d3; // expected-note {{'d3' defined here}}
 
   d.a = a;
   d2++;
   ;
-#pragma omp threadprivate(argc+y) // expected-error {{expected unqualified-id}}
+#pragma omp threadprivate(argc+y) // expected-error {{expected identifier}}
 #pragma omp threadprivate(argc,y) // expected-error 2 {{arguments of '#pragma omp threadprivate' must have static storage duration}}
 #pragma omp threadprivate(d2) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'd2'}}
 #pragma omp threadprivate(d1)





More information about the cfe-commits mailing list