r177705 - OpenMP threadprivate directive parsing and semantic analysis

Alexey Bataev a.bataev at hotmail.com
Thu Mar 21 23:34:36 PDT 2013


Author: abataev
Date: Fri Mar 22 01:34:35 2013
New Revision: 177705

URL: http://llvm.org/viewvc/llvm-project?rev=177705&view=rev
Log:
OpenMP threadprivate directive parsing and semantic analysis

Added:
    cfe/trunk/include/clang/AST/DeclOpenMP.h   (with props)
    cfe/trunk/include/clang/Basic/OpenMPKinds.def
    cfe/trunk/include/clang/Basic/OpenMPKinds.h   (with props)
    cfe/trunk/lib/AST/DeclOpenMP.cpp   (with props)
    cfe/trunk/lib/Basic/OpenMPKinds.cpp   (with props)
    cfe/trunk/lib/Parse/ParseOpenMP.cpp   (with props)
    cfe/trunk/lib/Sema/SemaOpenMP.cpp   (with props)
    cfe/trunk/test/OpenMP/no_option.c   (with props)
    cfe/trunk/test/OpenMP/no_option_no_warn.c   (with props)
    cfe/trunk/test/OpenMP/openmp_common.c   (with props)
    cfe/trunk/test/OpenMP/option_warn.c   (with props)
    cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp   (with props)
    cfe/trunk/test/OpenMP/threadprivate_messages.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/DeclVisitor.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/DeclNodes.td
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/TokenKinds.def
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Sema/Template.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/lib/AST/CMakeLists.txt
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/lib/Basic/CMakeLists.txt
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/Frontend/ASTConsumers.cpp
    cfe/trunk/lib/Parse/CMakeLists.txt
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParsePragma.cpp
    cfe/trunk/lib/Parse/ParsePragma.h
    cfe/trunk/lib/Parse/ParseStmt.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/CMakeLists.txt
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Serialization/ASTCommon.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/test/OpenMP/predefined_macro.c
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/RecursiveASTVisitor.h

Added: cfe/trunk/include/clang/AST/DeclOpenMP.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclOpenMP.h?rev=177705&view=auto
==============================================================================
--- cfe/trunk/include/clang/AST/DeclOpenMP.h (added)
+++ cfe/trunk/include/clang/AST/DeclOpenMP.h Fri Mar 22 01:34:35 2013
@@ -0,0 +1,83 @@
+//===--- OpenMP.h - Classes for representing OpenMP directives ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines OpenMP nodes.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_OPENMP_H
+#define LLVM_CLANG_AST_OPENMP_H
+
+#include "clang/AST/DeclBase.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace clang {
+
+class DeclRefExpr;
+
+/// \brief This represents '#pragma omp threadprivate ...' directive.
+/// For example, in the following, both 'a' and 'A::b' are threadprivate:
+///
+/// \code
+/// int a;
+/// #pragma omp threadprivate(a)
+/// struct A {
+///   static int b;
+/// #pragma omp threadprivate(b)
+/// };
+/// \endcode
+///
+class OMPThreadPrivateDecl : public Decl {
+  friend class ASTDeclReader;
+  unsigned NumVars;
+
+  virtual void anchor();
+
+  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),
+                   NumVars);
+  }
+
+  llvm::MutableArrayRef<DeclRefExpr *> getVars() {
+    return llvm::MutableArrayRef<DeclRefExpr *>(
+                                 reinterpret_cast<DeclRefExpr **>(this + 1),
+                                 NumVars);
+  }
+
+  void setVars(ArrayRef<DeclRefExpr *> VL);
+
+public:
+  static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
+                                      SourceLocation L,
+                                      ArrayRef<DeclRefExpr *> 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;
+
+  unsigned varlist_size() const { return NumVars; }
+  bool varlist_empty() const { return NumVars == 0; }
+  varlist_iterator varlist_begin() { return getVars().begin(); }
+  varlist_iterator varlist_end() { return getVars().end(); }
+  varlist_const_iterator varlist_begin() const { return getVars().begin(); }
+  varlist_const_iterator varlist_end() const { return getVars().end(); }
+
+  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+  static bool classofKind(Kind K) { return K == OMPThreadPrivate; }
+};
+
+}  // end namespace clang
+
+#endif

Propchange: cfe/trunk/include/clang/AST/DeclOpenMP.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/include/clang/AST/DeclOpenMP.h
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/include/clang/AST/DeclOpenMP.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/include/clang/AST/DeclVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclVisitor.h?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclVisitor.h (original)
+++ cfe/trunk/include/clang/AST/DeclVisitor.h Fri Mar 22 01:34:35 2013
@@ -17,6 +17,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclOpenMP.h"
 #include "clang/AST/DeclTemplate.h"
 
 namespace clang {

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Fri Mar 22 01:34:35 2013
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclOpenMP.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -1389,6 +1390,14 @@ DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
 
 DEF_TRAVERSE_DECL(UsingShadowDecl, { })
 
+DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, {
+    for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
+                                                E = D->varlist_end();
+         I != E; ++I) {
+      TRY_TO(TraverseStmt(*I));
+    }
+  })
+
 // A helper method for TemplateDecl's children.
 template<typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(

Modified: cfe/trunk/include/clang/Basic/DeclNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DeclNodes.td (original)
+++ cfe/trunk/include/clang/Basic/DeclNodes.td Fri Mar 22 01:34:35 2013
@@ -74,5 +74,6 @@ def StaticAssert : Decl;
 def Block : Decl, DeclContext;
 def ClassScopeFunctionSpecialization : Decl;
 def Import : Decl;
+def OMPThreadPrivate : Decl;
 def Empty : Decl;
 

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Fri Mar 22 01:34:35 2013
@@ -517,3 +517,6 @@ def ASMOperandWidths : DiagGroup<"asm-op
 def ASM : DiagGroup<"asm", [
     ASMOperandWidths
   ]>;
+
+// OpenMP warnings.
+def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Mar 22 01:34:35 2013
@@ -772,7 +772,18 @@ def err_seh___except_filter : Error<
 
 def err_seh___finally_block : Error<
   "%0 only allowed in __finally block">;
-  
+
+// OpenMP support.
+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">,
+  InGroup<ExtraTokens>;
+def err_omp_unknown_directive : Error <
+  "expected an OpenMP directive">;
+def err_omp_unexpected_directive : Error <
+  "unexpected OpenMP directive '#pragma omp %0'">;
+
 } // 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=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Mar 22 01:34:35 2013
@@ -6195,6 +6195,22 @@ def err_sampler_argument_required : Erro
 def err_wrong_sampler_addressspace: Error<
   "sampler type cannot be used with the __local and __global address space qualifiers">;
 
+// 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">;
+def err_omp_var_scope : Error<
+  "'#pragma omp %0' must appear in the scope of the %1 variable declaration">;
+def err_omp_var_used : Error<
+  "'#pragma omp %0' must precede all references to variable %1">;
+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
 
 let CategoryName = "Related Result Type Issue" in {

Added: cfe/trunk/include/clang/Basic/OpenMPKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=177705&view=auto
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenMPKinds.def (added)
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Fri Mar 22 01:34:35 2013
@@ -0,0 +1,23 @@
+//===--- OpenMPKinds.def - OpenMP directives and clauses list ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file defines the list of supported OpenMP directives and 
+/// clauses.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef OPENMP_DIRECTIVE
+#  define OPENMP_DIRECTIVE(Name)
+#endif
+
+// OpenMP directives.
+OPENMP_DIRECTIVE(threadprivate)
+OPENMP_DIRECTIVE(parallel)
+
+#undef OPENMP_DIRECTIVE

Added: cfe/trunk/include/clang/Basic/OpenMPKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.h?rev=177705&view=auto
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenMPKinds.h (added)
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.h Fri Mar 22 01:34:35 2013
@@ -0,0 +1,37 @@
+//===--- OpenMPKinds.h - OpenMP enums ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines some OpenMP-specific enums and functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_OPENMPKINDS_H
+#define LLVM_CLANG_BASIC_OPENMPKINDS_H
+
+#include "clang/Lex/Token.h"
+
+namespace clang {
+
+/// \brief OpenMP directives.
+enum OpenMPDirectiveKind {
+  OMPD_unknown = 0,
+#define OPENMP_DIRECTIVE(Name) \
+  OMPD_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+  NUM_OPENMP_DIRECTIVES
+};
+
+OpenMPDirectiveKind getOpenMPDirectiveKind(StringRef Str);
+const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
+
+}
+
+#endif
+

Propchange: cfe/trunk/include/clang/Basic/OpenMPKinds.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/include/clang/Basic/OpenMPKinds.h
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/include/clang/Basic/OpenMPKinds.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Fri Mar 22 01:34:35 2013
@@ -646,6 +646,12 @@ ANNOTATION(pragma_fp_contract)
 // handles them.
 ANNOTATION(pragma_opencl_extension)
 
+// Annotations for OpenMP pragma directives - #pragma omp ...
+// The lexer produces these so that they only take effect when the parser
+// handles #pragma omp ... directives.
+ANNOTATION(pragma_openmp)
+ANNOTATION(pragma_openmp_end)
+
 #undef ANNOTATION
 #undef TESTING_KEYWORD
 #undef OBJC2_AT_KEYWORD

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Mar 22 01:34:35 2013
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_PARSE_PARSER_H
 #define LLVM_CLANG_PARSE_PARSER_H
 
+#include "clang/Basic/OpenMPKinds.h"
 #include "clang/Basic/OperatorPrecedence.h"
 #include "clang/Basic/Specifiers.h"
 #include "clang/Lex/CodeCompletionHandler.h"
@@ -147,6 +148,7 @@ class Parser : public CodeCompletionHand
   OwningPtr<PragmaHandler> FPContractHandler;
   OwningPtr<PragmaHandler> OpenCLExtensionHandler;
   OwningPtr<CommentHandler> CommentSemaHandler;
+  OwningPtr<PragmaHandler> OpenMPHandler;
 
   /// Whether the '>' token acts as an operator or not. This will be
   /// true except when we are parsing an expression within a C++
@@ -2104,6 +2106,11 @@ private:
                                   ParsedType ObjectType,
                                   UnqualifiedId &Result);
 
+  //===--------------------------------------------------------------------===//
+  // OpenMP: Directives and clauses.
+  DeclGroupPtrTy ParseOpenMPDeclarativeDirective();
+  bool ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
+                                SmallVectorImpl<DeclarationNameInfo> &IdList);
 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=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Mar 22 01:34:35 2013
@@ -132,6 +132,7 @@ namespace clang {
   class ObjCMethodDecl;
   class ObjCPropertyDecl;
   class ObjCProtocolDecl;
+  class OMPThreadPrivateDecl;
   class OverloadCandidateSet;
   class OverloadExpr;
   class ParenListExpr;
@@ -6592,6 +6593,18 @@ public:
   void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T,
                       unsigned SpellingListIndex, bool IsPackExpansion);
 
+  // OpenMP directives and clauses.
+
+  /// \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.
+  OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(
+                        SourceLocation Loc,
+                        ArrayRef<DeclRefExpr *> VarList);
+
   /// \brief The kind of conversion being performed.
   enum CheckedConversionKind {
     /// \brief An implicit conversion.

Modified: cfe/trunk/include/clang/Sema/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Template.h (original)
+++ cfe/trunk/include/clang/Sema/Template.h Fri Mar 22 01:34:35 2013
@@ -430,6 +430,7 @@ namespace clang {
     Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
     Decl *VisitClassScopeFunctionSpecializationDecl(
                                       ClassScopeFunctionSpecializationDecl *D);
+    Decl *VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
 
     // Base case. FIXME: Remove once we can instantiate everything.
     Decl *VisitDecl(Decl *D) {

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Fri Mar 22 01:34:35 2013
@@ -1036,6 +1036,8 @@ namespace clang {
       DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
       /// \brief An ImportDecl recording a module import.
       DECL_IMPORT,
+      /// \brief A OMPThreadPrivateDecl record.
+      DECL_OMP_THREADPRIVATE,
       /// \brief An EmptyDecl record.
       DECL_EMPTY
     };

Modified: cfe/trunk/lib/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CMakeLists.txt (original)
+++ cfe/trunk/lib/AST/CMakeLists.txt Fri Mar 22 01:34:35 2013
@@ -22,6 +22,7 @@ add_clang_library(clangAST
   DeclFriend.cpp
   DeclGroup.cpp
   DeclObjC.cpp
+  DeclOpenMP.cpp
   DeclPrinter.cpp
   DeclTemplate.cpp
   DumpXML.cpp

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Fri Mar 22 01:34:35 2013
@@ -20,6 +20,7 @@
 #include "clang/AST/DeclContextInternals.h"
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclOpenMP.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DependentDiagnostic.h"
 #include "clang/AST/ExternalASTSource.h"
@@ -561,6 +562,7 @@ unsigned Decl::getIdentifierNamespaceFor
     case ObjCCategory:
     case ObjCCategoryImpl:
     case Import:
+    case OMPThreadPrivate:
     case Empty:
       // Never looked up by name.
       return 0;

Added: cfe/trunk/lib/AST/DeclOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclOpenMP.cpp?rev=177705&view=auto
==============================================================================
--- cfe/trunk/lib/AST/DeclOpenMP.cpp (added)
+++ cfe/trunk/lib/AST/DeclOpenMP.cpp Fri Mar 22 01:34:35 2013
@@ -0,0 +1,60 @@
+//===--- DeclOpenMP.cpp - Declaration OpenMP AST Node Implementation ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file implements OMPThreadPrivateDecl class.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclOpenMP.h"
+#include "clang/AST/Expr.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// OMPThreadPrivateDecl Implementation.
+//===----------------------------------------------------------------------===//
+
+void OMPThreadPrivateDecl::anchor() { }
+
+OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
+                                                   DeclContext *DC,
+                                                   SourceLocation L,
+                                                   ArrayRef<DeclRefExpr *> VL) {
+  unsigned Size = sizeof(OMPThreadPrivateDecl) +
+                  (VL.size() * sizeof(DeclRefExpr *));
+
+  void *Mem = C.Allocate(Size, llvm::alignOf<OMPThreadPrivateDecl>());
+  OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate,
+                                                           DC, L);
+  D->NumVars = VL.size();
+  D->setVars(VL);
+  return D;
+}
+
+OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C,
+                                                               unsigned ID,
+                                                               unsigned N) {
+  unsigned Size = sizeof(OMPThreadPrivateDecl) + (N * sizeof(DeclRefExpr *));
+
+  void *Mem = AllocateDeserializedDecl(C, ID, Size);
+  OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate,
+                                                           0, SourceLocation());
+  D->NumVars = N;
+  return D;
+}
+
+void OMPThreadPrivateDecl::setVars(ArrayRef<DeclRefExpr *> VL) {
+  assert(VL.size() == NumVars &&
+         "Number of variables is not the same as the preallocated buffer");
+  DeclRefExpr **Vars = reinterpret_cast<DeclRefExpr **>(this + 1);
+  std::copy(VL.begin(), VL.end(), Vars);
+}

Propchange: cfe/trunk/lib/AST/DeclOpenMP.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/lib/AST/DeclOpenMP.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/lib/AST/DeclOpenMP.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Fri Mar 22 01:34:35 2013
@@ -82,6 +82,7 @@ namespace {
     void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
     void VisitUsingDecl(UsingDecl *D);
     void VisitUsingShadowDecl(UsingShadowDecl *D);
+    void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
 
     void PrintTemplateParameters(const TemplateParameterList *Params,
                                  const TemplateArgumentList *Args = 0);
@@ -291,8 +292,10 @@ void DeclPrinter::VisitDeclContext(DeclC
 
     // FIXME: Need to be able to tell the DeclPrinter when
     const char *Terminator = 0;
-    if (isa<FunctionDecl>(*D) &&
-        cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
+    if (isa<OMPThreadPrivateDecl>(*D))
+      Terminator = 0;
+    else if (isa<FunctionDecl>(*D) &&
+             cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
       Terminator = 0;
     else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
       Terminator = 0;
@@ -1150,3 +1153,17 @@ void DeclPrinter::VisitUnresolvedUsingVa
 void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
   // ignore
 }
+
+void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
+  Out << "#pragma omp threadprivate";
+  if (!D->varlist_empty()) {
+    for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
+                                                E = D->varlist_end();
+         I != E; ++I) {
+      Out << (I == D->varlist_begin() ? '(' : ',')
+          << *cast<NamedDecl>((*I)->getDecl());
+    }
+    Out << ")";
+  }
+}
+

Modified: cfe/trunk/lib/Basic/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/CMakeLists.txt?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/CMakeLists.txt (original)
+++ cfe/trunk/lib/Basic/CMakeLists.txt Fri Mar 22 01:34:35 2013
@@ -11,6 +11,7 @@ add_clang_library(clangBasic
   LangOptions.cpp
   Module.cpp
   ObjCRuntime.cpp
+  OpenMPKinds.cpp
   OperatorPrecedence.cpp
   SourceLocation.cpp
   SourceManager.cpp

Added: cfe/trunk/lib/Basic/OpenMPKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=177705&view=auto
==============================================================================
--- cfe/trunk/lib/Basic/OpenMPKinds.cpp (added)
+++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Fri Mar 22 01:34:35 2013
@@ -0,0 +1,43 @@
+//===--- OpenMPKinds.cpp - Token Kinds Support ----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file implements the OpenMP enum and support functions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+
+using namespace clang;
+
+OpenMPDirectiveKind clang::getOpenMPDirectiveKind(StringRef Str) {
+  return llvm::StringSwitch<OpenMPDirectiveKind>(Str)
+#define OPENMP_DIRECTIVE(Name) \
+           .Case(#Name, OMPD_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+           .Default(OMPD_unknown);
+}
+
+const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) {
+  assert(Kind < NUM_OPENMP_DIRECTIVES);
+  switch (Kind) {
+  case OMPD_unknown:
+    return ("unknown");
+#define OPENMP_DIRECTIVE(Name) \
+  case OMPD_##Name : return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+  default:
+    break;
+  }
+  llvm_unreachable("Invalid OpenMP directive kind");
+}

Propchange: cfe/trunk/lib/Basic/OpenMPKinds.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/lib/Basic/OpenMPKinds.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/lib/Basic/OpenMPKinds.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Mar 22 01:34:35 2013
@@ -83,6 +83,7 @@ void CodeGenFunction::EmitDecl(const Dec
   case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
   case Decl::Label:        // __label__ x;
   case Decl::Import:
+  case Decl::OMPThreadPrivate:
   case Decl::Empty:
     // None of these decls require codegen support.
     return;

Modified: cfe/trunk/lib/Frontend/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTConsumers.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTConsumers.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTConsumers.cpp Fri Mar 22 01:34:35 2013
@@ -463,6 +463,10 @@ void DeclContextPrinter::PrintDeclContex
       Out << "<class template> " << *CTD << '\n';
       break;
     }
+    case Decl::OMPThreadPrivate: {
+      Out << "<omp threadprivate> " << '"' << *I << "\"\n";
+      break;
+    }
     default:
       Out << "DeclKind: " << DK << '"' << *I << "\"\n";
       llvm_unreachable("decl unhandled");

Modified: cfe/trunk/lib/Parse/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/CMakeLists.txt?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/CMakeLists.txt (original)
+++ cfe/trunk/lib/Parse/CMakeLists.txt Fri Mar 22 01:34:35 2013
@@ -7,6 +7,7 @@ add_clang_library(clangParse
   ParseExprCXX.cpp
   ParseInit.cpp
   ParseObjc.cpp
+  ParseOpenMP.cpp
   ParsePragma.cpp
   ParseStmt.cpp
   ParseTemplate.cpp

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Mar 22 01:34:35 2013
@@ -2525,6 +2525,11 @@ void Parser::ParseCXXMemberSpecification
         continue;
       }
 
+      if (Tok.is(tok::annot_pragma_openmp)) {
+        ParseOpenMPDeclarativeDirective();
+        continue;
+      }
+
       AccessSpecifier AS = getAccessSpecifierIfPresent();
       if (AS != AS_none) {
         // Current token is a C++ access specifier.

Added: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=177705&view=auto
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (added)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Fri Mar 22 01:34:35 2013
@@ -0,0 +1,118 @@
+//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file implements parsing of all OpenMP directives and clauses.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "RAIIObjectsForParser.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// OpenMP declarative directives.
+//===----------------------------------------------------------------------===//
+
+/// \brief Parses OpenMP declarative directive
+///       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) {
+  case OMPD_threadprivate:
+    ConsumeToken();
+    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers)) {
+      // The last seen token is annot_pragma_openmp_end - need to check for
+      // extra tokens.
+      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
+        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
+          << getOpenMPDirectiveName(OMPD_threadprivate);
+        SkipUntil(tok::annot_pragma_openmp_end, false, true);
+      }
+      ConsumeToken();
+      return Actions.ActOnOpenMPThreadprivateDirective(Loc,
+                                                       getCurScope(),
+                                                       Identifiers);
+    }
+    break;
+  case OMPD_unknown:
+    Diag(Tok, diag::err_omp_unknown_directive);
+    break;
+  default:
+    Diag(Tok, diag::err_omp_unexpected_directive)
+      << getOpenMPDirectiveName(Kind);
+    break;
+  }
+  SkipUntil(tok::annot_pragma_openmp_end, false);
+  return DeclGroupPtrTy();
+}
+
+/// \brief Parses list of simple variables for '#pragma omp threadprivate'
+/// directive
+/// simple-variable-list:
+///   ( unqualified-id {, unqualified-id} ) annot_pragma_openmp_end
+///
+bool Parser::ParseOpenMPSimpleVarList(
+  OpenMPDirectiveKind Kind,
+  SmallVectorImpl<DeclarationNameInfo> &IdList) {
+  // 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;
+  }
+
+  // Read tokens while ')' or annot_pragma_openmp_end is not found.
+  do {
+    CXXScopeSpec SS;
+    SourceLocation TemplateKWLoc;
+    UnqualifiedId Name;
+    // Read var name.
+    Token PrevTok = Tok;
+
+    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
+        << SourceRange(PrevTok.getLocation(), PrevTokLocation);
+    } else {
+      IdList.push_back(Actions.GetNameFromUnqualifiedId(Name));
+    }
+    // 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;
+  }
+
+  return !IsCorrect && IdList.empty();
+}

Propchange: cfe/trunk/lib/Parse/ParseOpenMP.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/lib/Parse/ParseOpenMP.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/lib/Parse/ParseOpenMP.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/lib/Parse/ParsePragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParsePragma.cpp (original)
+++ cfe/trunk/lib/Parse/ParsePragma.cpp Fri Mar 22 01:34:35 2013
@@ -718,3 +718,47 @@ PragmaOpenCLExtensionHandler::HandlePrag
                       /*OwnsTokens=*/false);
 }
 
+/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
+///
+void
+PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
+                                    PragmaIntroducerKind Introducer,
+                                    Token &FirstTok) {
+  if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
+                                             FirstTok.getLocation()) !=
+      DiagnosticsEngine::Ignored) {
+    PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
+    PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
+                                             diag::MAP_IGNORE,
+                                             SourceLocation());
+  }
+  PP.DiscardUntilEndOfDirective();
+}
+
+/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
+///
+void
+PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
+                                  PragmaIntroducerKind Introducer,
+                                  Token &FirstTok) {
+  SmallVector<Token, 16> Pragma;
+  Token Tok;
+  Tok.startToken();
+  Tok.setKind(tok::annot_pragma_openmp);
+  Tok.setLocation(FirstTok.getLocation());
+
+  while (Tok.isNot(tok::eod)) {
+    Pragma.push_back(Tok);
+    PP.Lex(Tok);
+  }
+  SourceLocation EodLoc = Tok.getLocation();
+  Tok.startToken();
+  Tok.setKind(tok::annot_pragma_openmp_end);
+  Tok.setLocation(EodLoc);
+  Pragma.push_back(Tok);
+
+  Token *Toks = new Token[Pragma.size()];
+  std::copy(Pragma.begin(), Pragma.end(), Toks);
+  PP.EnterTokenStream(Toks, Pragma.size(),
+                      /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
+}

Modified: cfe/trunk/lib/Parse/ParsePragma.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.h?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParsePragma.h (original)
+++ cfe/trunk/lib/Parse/ParsePragma.h Fri Mar 22 01:34:35 2013
@@ -98,7 +98,20 @@ public:
   virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
                             Token &FirstToken);
 };
-  
+
+class PragmaNoOpenMPHandler : public PragmaHandler {
+public:
+  PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
+  virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+                            Token &FirstToken);
+};
+
+class PragmaOpenMPHandler : public PragmaHandler {
+public:
+  PragmaOpenMPHandler() : PragmaHandler("omp") { }
+  virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+                            Token &FirstToken);
+};
 
 }  // end namespace clang
 

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Fri Mar 22 01:34:35 2013
@@ -288,6 +288,11 @@ Retry:
     ProhibitAttributes(Attrs);
     HandlePragmaOpenCLExtension();
     return StmtEmpty();
+
+  case tok::annot_pragma_openmp:
+    SourceLocation DeclStart = Tok.getLocation();
+    DeclGroupPtrTy Res = ParseOpenMPDeclarativeDirective();
+    return Actions.ActOnDeclStmt(Res, DeclStart, Tok.getLocation());
   }
 
   // If we reached this code, the statement must end in a semicolon.

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Fri Mar 22 01:34:35 2013
@@ -96,6 +96,11 @@ Parser::Parser(Preprocessor &pp, Sema &a
 
     PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
   }
+  if (getLangOpts().OpenMP)
+    OpenMPHandler.reset(new PragmaOpenMPHandler());
+  else
+    OpenMPHandler.reset(new PragmaNoOpenMPHandler());
+  PP.AddPragmaHandler(OpenMPHandler.get());
 
   CommentSemaHandler.reset(new ActionCommentHandler(actions));
   PP.addCommentHandler(CommentSemaHandler.get());
@@ -428,6 +433,8 @@ Parser::~Parser() {
     OpenCLExtensionHandler.reset();
     PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
   }
+  PP.RemovePragmaHandler(OpenMPHandler.get());
+  OpenMPHandler.reset();
 
   PP.RemovePragmaHandler("STDC", FPContractHandler.get());
   FPContractHandler.reset();
@@ -624,6 +631,9 @@ Parser::ParseExternalDeclaration(ParsedA
   case tok::annot_pragma_opencl_extension:
     HandlePragmaOpenCLExtension();
     return DeclGroupPtrTy();
+  case tok::annot_pragma_openmp:
+    ParseOpenMPDeclarativeDirective();
+    return DeclGroupPtrTy();
   case tok::semi:
     // Either a C++11 empty-declaration or attribute-declaration.
     SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),

Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Fri Mar 22 01:34:35 2013
@@ -38,6 +38,7 @@ add_clang_library(clangSema
   SemaLambda.cpp
   SemaLookup.cpp
   SemaObjCProperty.cpp
+  SemaOpenMP.cpp
   SemaOverload.cpp
   SemaPseudoObject.cpp
   SemaStmt.cpp

Added: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=177705&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (added)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Fri Mar 22 01:34:35 2013
@@ -0,0 +1,181 @@
+//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file implements semantic analysis for OpenMP directives and
+/// clauses
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclOpenMP.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+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;
+      }
+  };
+}
+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();
+        }
+      } else {
+        Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
+          << I->getName() << Corrected.isResolved() << CorrectedQuotedStr
+          << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
+      }
+      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;
+    }
+
+    // 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, 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;
+    }
+
+    QualType ExprType = VD->getType().getNonReferenceType();
+    DeclRefExpr *Var = cast<DeclRefExpr>(BuildDeclRefExpr(VD,
+                                                          ExprType,
+                                                          VK_RValue,
+                                                          I->getLoc()).take());
+    Vars.push_back(Var);
+  }
+  if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, Vars)) {
+    CurContext->addDecl(D);
+    return DeclGroupPtrTy::make(DeclGroupRef(D));
+  }
+  return DeclGroupPtrTy();
+}
+
+OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
+                                 SourceLocation Loc,
+                                 ArrayRef<DeclRefExpr *> VarList) {
+  SmallVector<DeclRefExpr *, 5> Vars;
+  for (ArrayRef<DeclRefExpr *>::iterator I = VarList.begin(),
+                                         E = VarList.end();
+       I != E; ++I) {
+    VarDecl *VD = cast<VarDecl>((*I)->getDecl());
+    SourceLocation ILoc = (*I)->getLocation();
+
+    // 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)) {
+      continue;
+    }
+
+    // OpenMP [2.9.2, Restrictions, C/C++, p.10]
+    //   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;
+      continue;
+    }
+
+    // Check if threadspecified is set.
+    if (VD->isThreadSpecified()) {
+      Diag(ILoc, diag::err_omp_var_thread_local) << VD;
+      Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+      continue;
+    }
+
+    Vars.push_back(*I);
+  }
+  return Vars.empty() ?
+              0 : OMPThreadPrivateDecl::Create(Context,
+                                               getCurLexicalContext(),
+                                               Loc, Vars);
+}

Propchange: cfe/trunk/lib/Sema/SemaOpenMP.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/lib/Sema/SemaOpenMP.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/lib/Sema/SemaOpenMP.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Mar 22 01:34:35 2013
@@ -2183,6 +2183,23 @@ Decl *TemplateDeclInstantiator::VisitCla
   return NewFD;
 }
 
+Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
+                                     OMPThreadPrivateDecl *D) {
+  SmallVector<DeclRefExpr *, 5> Vars;
+  for (ArrayRef<DeclRefExpr *>::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));
+  }
+
+  OMPThreadPrivateDecl *TD =
+    SemaRef.CheckOMPThreadPrivateDecl(D->getLocation(), Vars);
+
+  return TD;
+}
+
 Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
                       const MultiLevelTemplateArgumentList &TemplateArgs) {
   TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);

Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.cpp Fri Mar 22 01:34:35 2013
@@ -204,6 +204,7 @@ bool serialization::isRedeclarableDeclKi
   case Decl::Block:
   case Decl::ClassScopeFunctionSpecialization:
   case Decl::Import:
+  case Decl::OMPThreadPrivate:
     return false;
   }
 

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Mar 22 01:34:35 2013
@@ -289,6 +289,7 @@ namespace clang {
     void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
     void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
     void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
+    void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
   };
 }
 
@@ -1626,6 +1627,17 @@ void ASTDeclReader::mergeRedeclarable(Re
   }
 }
 
+void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
+  VisitDecl(D);
+  unsigned NumVars = D->varlist_size();
+  SmallVector<DeclRefExpr *, 16> Vars;
+  Vars.reserve(NumVars);
+  for (unsigned i = 0; i != NumVars; ++i) {
+    Vars.push_back(cast<DeclRefExpr>(Reader.ReadExpr(F)));
+  }
+  D->setVars(Vars);
+}
+
 //===----------------------------------------------------------------------===//
 // Attribute Reading
 //===----------------------------------------------------------------------===//
@@ -2134,6 +2146,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID I
     // locations.
     D = ImportDecl::CreateDeserialized(Context, ID, Record.back());
     break;
+  case DECL_OMP_THREADPRIVATE:
+    D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record[Idx++]);
+    break;
   case DECL_EMPTY:
     D = EmptyDecl::CreateDeserialized(Context, ID);
     break;

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Mar 22 01:34:35 2013
@@ -123,6 +123,7 @@ namespace clang {
     void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
     void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
     void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
+    void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
   };
 }
 
@@ -1314,6 +1315,16 @@ void ASTDeclWriter::VisitRedeclarable(Re
   
 }
 
+void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
+  Record.push_back(D->varlist_size());
+  VisitDecl(D);
+  for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
+                                              E = D->varlist_end();
+       I != E; ++I)
+    Writer.AddStmt(*I);
+  Code = serialization::DECL_OMP_THREADPRIVATE;
+}
+
 //===----------------------------------------------------------------------===//
 // ASTWriter Implementation
 //===----------------------------------------------------------------------===//

Added: cfe/trunk/test/OpenMP/no_option.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/no_option.c?rev=177705&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/no_option.c (added)
+++ cfe/trunk/test/OpenMP/no_option.c Fri Mar 22 01:34:35 2013
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -verify -o - %s
+// expected-no-diagnostics
+
+int a;
+#pragma omp threadprivate(a,b)
+#pragma omp parallel

Propchange: cfe/trunk/test/OpenMP/no_option.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/no_option.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/no_option.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/no_option_no_warn.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/no_option_no_warn.c?rev=177705&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/no_option_no_warn.c (added)
+++ cfe/trunk/test/OpenMP/no_option_no_warn.c Fri Mar 22 01:34:35 2013
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -verify -Wno-source-uses-openmp -o - %s
+// expected-no-diagnostics
+
+int a;
+#pragma omp threadprivate(a,b)
+#pragma omp parallel

Propchange: cfe/trunk/test/OpenMP/no_option_no_warn.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/no_option_no_warn.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/no_option_no_warn.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/openmp_common.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/openmp_common.c?rev=177705&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/openmp_common.c (added)
+++ cfe/trunk/test/OpenMP/openmp_common.c Fri Mar 22 01:34:35 2013
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+
+#pragma omp // expected-error {{expected an OpenMP directive}}
+#pragma omp unknown_directive // expected-error {{expected an OpenMP directive}}
+
+void foo() {
+#pragma omp // expected-error {{expected an OpenMP directive}}
+#pragma omp unknown_directive // expected-error {{expected an OpenMP directive}}
+}

Propchange: cfe/trunk/test/OpenMP/openmp_common.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/openmp_common.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/openmp_common.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/option_warn.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/option_warn.c?rev=177705&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/option_warn.c (added)
+++ cfe/trunk/test/OpenMP/option_warn.c Fri Mar 22 01:34:35 2013
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -verify -Wsource-uses-openmp -o - %s
+
+int a;
+#pragma omp threadprivate(a,b) // expected-warning {{unexpected '#pragma omp ...' in program}}
+#pragma omp parallel

Propchange: cfe/trunk/test/OpenMP/option_warn.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/option_warn.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/option_warn.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/test/OpenMP/predefined_macro.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/predefined_macro.c?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/predefined_macro.c (original)
+++ cfe/trunk/test/OpenMP/predefined_macro.c Fri Mar 22 01:34:35 2013
@@ -7,6 +7,23 @@
 #error "No _OPENMP macro is defined with -fopenmp option"
 #elsif _OPENMP != 201107
 #error "_OPENMP has incorrect value"
+#endif //_OPENMP
+#else
+// No -fopenmp option is specified
+#ifdef _OPENMP
+#error "_OPENMP macro is defined without -fopenmp option"
+#endif // _OPENMP
+#endif // FOPENMP
+
+// RUN: %clang_cc1 -fopenmp -verify -DFOPENMP -o - %s
+// RUN: %clang_cc1 -verify -o - %s
+// expected-no-diagnostics
+#ifdef FOPENMP
+// -fopenmp option is specified
+#ifndef _OPENMP
+#error "No _OPENMP macro is defined with -fopenmp option"
+#elsif _OPENMP != 201107
+#error "_OPENMP has incorrect value"
 #endif // _OPENMP
 #else
 // No -fopenmp option is specified

Added: cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp?rev=177705&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp (added)
+++ cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp Fri Mar 22 01:34:35 2013
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// expected-no-diagnostics
+
+struct St{
+ int a;
+};
+
+struct St1{
+ int a;
+ static int b;
+// CHECK: static int b;
+#pragma omp threadprivate(b)
+// CHECK-NEXT: #pragma omp threadprivate(b)
+} d;
+
+int a, b;
+// CHECK: int a;
+// CHECK: int b;
+#pragma omp threadprivate(a)
+// CHECK-NEXT: #pragma omp threadprivate(a)
+#pragma omp threadprivate(d, b)
+// CHECK-NEXT: #pragma omp threadprivate(d,b)
+
+template <class T> T foo() {
+  static T v;
+  #pragma omp threadprivate(v)
+  return v;
+}
+//CHECK: template <class T = int> int foo() {
+//CHECK-NEXT: static int v;
+//CHECK-NEXT: #pragma omp threadprivate(v)
+//CHECK: template <class T> T foo() {
+//CHECK-NEXT: static T v;
+//CHECK-NEXT: #pragma omp threadprivate(v)
+
+int main () {
+  static int a;
+// CHECK: static int a;
+#pragma omp threadprivate(a)
+// CHECK-NEXT: #pragma omp threadprivate(a)
+  a=2;
+  return (foo<int>());
+}

Propchange: cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/threadprivate_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/threadprivate_messages.cpp?rev=177705&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/threadprivate_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/threadprivate_messages.cpp Fri Mar 22 01:34:35 2013
@@ -0,0 +1,119 @@
+// 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(1) // expected-error {{expected unqualified-id}}
+struct CompleteSt{
+ int a;
+};
+
+struct CompleteSt1{
+#pragma omp threadprivate(1) // expected-error {{expected unqualified-id}}
+ int a;
+} d; // expected-note {{forward declaration of 'd'}}
+
+int a; // expected-note {{forward declaration of 'a'}}
+
+#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}}
+  return (a);
+}
+
+#pragma omp threadprivate a // expected-error {{expected '(' after 'threadprivate'}}
+#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))
+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(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((float)a) // expected-error {{expected unqualified-id}}
+int foa;
+#pragma omp threadprivate(faa) // expected-error {{use of undeclared identifier 'faa'; did you mean 'foa'?}}
+#pragma omp threadprivate(foo) // expected-error {{'foo' is not a global variable, static local variable or static data member}}
+#pragma omp threadprivate (int a=2) // expected-error {{expected unqualified-id}}
+
+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'}}
+
+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 &'}}
+
+class Class {
+  private:
+    int a; // expected-note {{declared here}}
+    static int b;
+    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 (g)
+
+namespace ns {
+  int m;
+#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}}
+
+const int h = 12;
+const volatile int i = 10;
+#pragma omp threadprivate (h, i)
+
+
+template <class T>
+class TempClass {
+  private:
+    T a;
+    TempClass() : a(){}
+  public:
+    TempClass (T aaa) : a(aaa) {}
+    static T s;
+#pragma omp threadprivate (s)
+};
+#pragma omp threadprivate (s) // expected-error {{use of undeclared identifier 's'}}
+
+static __thread int t; // expected-note {{forward declaration of 't'}}
+#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'}}
+namespace {
+int o; // expected-note {{candidate found by name lookup is '<anonymous namespace>::o'}}
+}
+#pragma omp threadprivate (o) // expected-error {{reference to 'o' is ambiguous}}
+
+int main(int argc, char **argv) { // expected-note {{forward declaration of 'argc'}}
+
+  int x, y = argc; // expected-note {{forward declaration of 'y'}}
+  static double d1;
+  static double d2;
+  static double d3; // expected-note {{forward declaration of 'd3'}}
+
+  d.a = a;
+  d2++;
+  ;
+#pragma omp threadprivate(argc+y) // expected-error {{expected unqualified-id}}
+#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)
+  {
+  ++a;d2=0;
+#pragma omp threadprivate(d3) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'd3' variable declaration}}
+  }
+#pragma omp threadprivate(d3)
+
+#pragma omp threadprivate(a) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'a' variable declaration}}
+  return (y);
+#pragma omp threadprivate(d) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'd' variable declaration}}
+}

Propchange: cfe/trunk/test/OpenMP/threadprivate_messages.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/threadprivate_messages.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/threadprivate_messages.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Fri Mar 22 01:34:35 2013
@@ -4458,6 +4458,7 @@ CXCursor clang_getCursorDefinition(CXCur
   case Decl::Label:  // FIXME: Is this right??
   case Decl::ClassScopeFunctionSpecialization:
   case Decl::Import:
+  case Decl::OMPThreadPrivate:
     return C;
 
   // Declaration kinds that don't make any sense here, but are

Modified: cfe/trunk/tools/libclang/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/RecursiveASTVisitor.h?rev=177705&r1=177704&r2=177705&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/RecursiveASTVisitor.h (original)
+++ cfe/trunk/tools/libclang/RecursiveASTVisitor.h Fri Mar 22 01:34:35 2013
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclOpenMP.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -1325,6 +1326,14 @@ DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
 
 DEF_TRAVERSE_DECL(UsingShadowDecl, { })
 
+DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, {
+    for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
+                                                E = D->varlist_end();
+         I != E; ++I) {
+      TRY_TO(TraverseStmt(*I));
+    }
+  })
+
 // A helper method for TemplateDecl's children.
 template<typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(





More information about the cfe-commits mailing list