Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td	(revision 166387)
+++ include/clang/Basic/DiagnosticGroups.td	(working copy)
@@ -251,6 +251,7 @@
 def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">;
 def Uninitialized  : DiagGroup<"uninitialized", [UninitializedSometimes]>;
 def UnknownPragmas : DiagGroup<"unknown-pragmas">;
+def OpenMPPragmas  : DiagGroup<"openmp-pragmas">;
 def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
 def UnknownAttributes : DiagGroup<"attributes">;
 def IgnoredAttributes : DiagGroup<"ignored-attributes">;
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td	(revision 166387)
+++ include/clang/Basic/DiagnosticParseKinds.td	(working copy)
@@ -734,6 +734,11 @@
   "'#pragma fp_contract' should only appear at file scope or at the start of a "
   "compound expression">; 
 
+// OpenMP
+def warn_pragma_omp_ignored : Warning<
+  "pragma omp ignored; did you forget to add '-fopenmp' flag?">,
+  InGroup<OpenMPPragmas>;
+
 // OpenCL Section 6.8.g
 def err_not_opencl_storage_class_specifier : Error<
   "OpenCL does not support the '%0' storage class specifier">;
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def	(revision 166387)
+++ include/clang/Basic/TokenKinds.def	(working copy)
@@ -637,6 +637,25 @@
 // handles them.
 ANNOTATION(pragma_opencl_extension)
 
+// Annotations for OpenMP pragma directive statements - "\#pragam omp ..."
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_omp_parallel)
+ANNOTATION(pragma_omp_for)
+ANNOTATION(pragma_omp_sections)
+ANNOTATION(pragma_omp_section)
+ANNOTATION(pragma_omp_single)
+ANNOTATION(pragma_omp_task)
+ANNOTATION(pragma_omp_master)
+ANNOTATION(pragma_omp_critical)
+ANNOTATION(pragma_omp_barrier)
+ANNOTATION(pragma_omp_taskwait)
+ANNOTATION(pragma_omp_taskyield)
+ANNOTATION(pragma_omp_atomic)
+ANNOTATION(pragma_omp_flush)
+ANNOTATION(pragma_omp_ordered)
+ANNOTATION(pragma_omp_threadprivate)
+
 #undef ANNOTATION
 #undef TESTING_KEYWORD
 #undef OBJC2_AT_KEYWORD
Index: include/clang/Lex/Preprocessor.h
===================================================================
--- include/clang/Lex/Preprocessor.h	(revision 166387)
+++ include/clang/Lex/Preprocessor.h	(working copy)
@@ -161,6 +161,13 @@
   /// \brief True if we are pre-expanding macro arguments.
   bool InMacroArgPreExpansion;
 
+  /// \brief When an OpenMP pragma is ignored, we emit a warning message saying
+  /// so, but only once per translation unit irrespective of the number of
+  /// OpenMP pragmas appeared in the translation unit. This flag keeps track of
+  /// whether the unkown pragma warning message is emitted or not for the 
+  /// current translation unit.
+  bool PragmaOmpUnknownWarning;
+
   /// Identifiers - This is mapping/lookup information for all identifiers in
   /// the program, including program keywords.
   mutable IdentifierTable Identifiers;
@@ -1396,6 +1403,13 @@
   /// \brief A macro is used, update information about macros that need unused
   /// warnings.
   void markMacroAsUsed(MacroInfo *MI);
+
+  /// \brief When source contains omp pragmas, but user does not pass the
+  /// '-fopenmp' flag, we emit a warning message saying so, but only once per
+  /// source file.
+  void SetPragmaOmpUnknownWarning() { PragmaOmpUnknownWarning = true; }
+  void ResetPragmaOmpUnknownWarning() { PragmaOmpUnknownWarning = false; }
+  bool GetPragmaOmpUnknownWarning() { return PragmaOmpUnknownWarning; }
 };
 
 /// \brief Abstract base class that describes a handler that will receive
Index: lib/Lex/Preprocessor.cpp
===================================================================
--- lib/Lex/Preprocessor.cpp	(revision 166387)
+++ lib/Lex/Preprocessor.cpp	(working copy)
@@ -103,6 +103,10 @@
   // This gets unpoisoned where it is allowed.
   (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned();
   SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use);
+
+  // We have not yet reported the unknown OpenMP pragma *warning* message
+  // as we have not yet started the processing of translation unit.
+  ResetPragmaOmpUnknownWarning();
   
   // Initialize the pragma handlers.
   PragmaHandlers = new PragmaNamespace(StringRef());
Index: lib/Parse/ParsePragma.h
===================================================================
--- lib/Parse/ParsePragma.h	(revision 166387)
+++ lib/Parse/ParsePragma.h	(working copy)
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_PARSE_PARSEPRAGMA_H
 #define LLVM_CLANG_PARSE_PARSEPRAGMA_H
 
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/Pragma.h"
 
 namespace clang {
@@ -98,6 +99,14 @@
   virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
                             Token &FirstToken);
 };
+
+struct PragmaOmpHandler : public PragmaHandler {
+  tok::TokenKind TKind;
+  PragmaOmpHandler(tok::TokenKind Kind, StringRef Name)
+  : PragmaHandler(Name), TKind(Kind) {}
+  virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+                            Token &OmpTok);
+};
   
 
 }  // end namespace clang
Index: lib/Parse/ParsePragma.cpp
===================================================================
--- lib/Parse/ParsePragma.cpp	(revision 166387)
+++ lib/Parse/ParsePragma.cpp	(working copy)
@@ -718,3 +718,30 @@
                       /*OwnsTokens=*/false);
 }
 
+/// Handle "\#pragma omp ...".
+///
+/// \brief Check if the user has passed the flag, '-fopenmp', if so, enter
+/// the *token* which is *representing* the current OpenMP pragma *directive*
+/// into the TokenStream, so that the Parser can recognizes it and can parse
+/// the respective OpenMP pragma directive statement.
+/// Otherwise, report a warning that the current OpenMP directive statement
+/// will be ignored. However, note that only *one* warning message per
+/// translation unit is reported irrespective of the number of OpenMP
+/// directive statments which appear in the translation unit.
+void PragmaOmpHandler::HandlePragma(Preprocessor &PP,
+                                    PragmaIntroducerKind Introducer,
+                                    Token &OmpTok) {
+  if (!PP.getLangOpts().OpenMP) {
+    if (!PP.GetPragmaOmpUnknownWarning()) {
+      PP.Diag(OmpTok, diag::warn_pragma_omp_ignored);
+      PP.SetPragmaOmpUnknownWarning();
+    }
+  } else {
+    Token *Toks = new Token[1];
+    Toks[0].startToken();
+    Toks[0].setKind(TKind);
+    Toks[0].setLocation(OmpTok.getLocation());
+    PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
+                        /*OwnsTokens=*/false);
+  }
+}
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 166387)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -178,6 +178,21 @@
   OwningPtr<PragmaHandler> RedefineExtnameHandler;
   OwningPtr<PragmaHandler> FPContractHandler;
   OwningPtr<PragmaHandler> OpenCLExtensionHandler;
+  OwningPtr<PragmaHandler> OpenMPParallelHandler;
+  OwningPtr<PragmaHandler> OpenMPForHandler;
+  OwningPtr<PragmaHandler> OpenMPSectionsHandler;
+  OwningPtr<PragmaHandler> OpenMPSectionHandler;
+  OwningPtr<PragmaHandler> OpenMPSingleHandler;
+  OwningPtr<PragmaHandler> OpenMPTaskHandler;
+  OwningPtr<PragmaHandler> OpenMPMasterHandler;
+  OwningPtr<PragmaHandler> OpenMPCriticalHandler;
+  OwningPtr<PragmaHandler> OpenMPBarrierHandler;
+  OwningPtr<PragmaHandler> OpenMPTaskwaitHandler;
+  OwningPtr<PragmaHandler> OpenMPTaskyieldHandler;
+  OwningPtr<PragmaHandler> OpenMPAtomicHandler;
+  OwningPtr<PragmaHandler> OpenMPFlushHandler;
+  OwningPtr<PragmaHandler> OpenMPOrderedHandler;
+  OwningPtr<PragmaHandler> OpenMPThreadPrivateHandler;
   OwningPtr<CommentHandler> CommentSemaHandler;
 
   /// Whether the '>' token acts as an operator or not. This will be
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp	(revision 166387)
+++ lib/Parse/Parser.cpp	(working copy)
@@ -98,6 +98,68 @@
   PP.addCommentHandler(CommentSemaHandler.get());
 
   PP.setCodeCompletionHandler(*this);
+
+  // Add "#pragma omp ..." handlers. These are removed and destroyed
+  // in the destructor.
+  OpenMPParallelHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_parallel, "parallel"));
+  PP.AddPragmaHandler("omp", OpenMPParallelHandler.get());
+
+  OpenMPForHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_for, "for"));
+  PP.AddPragmaHandler("omp", OpenMPForHandler.get());
+
+  OpenMPSectionsHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_sections, "sections"));
+  PP.AddPragmaHandler("omp", OpenMPSectionsHandler.get());
+
+  OpenMPSectionHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_section, "section"));
+  PP.AddPragmaHandler("omp", OpenMPSectionHandler.get());
+
+  OpenMPSingleHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_single, "single"));
+  PP.AddPragmaHandler("omp", OpenMPSingleHandler.get());
+
+  OpenMPTaskHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_task, "task"));
+  PP.AddPragmaHandler("omp", OpenMPTaskHandler.get());
+
+  OpenMPMasterHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_master, "master"));
+  PP.AddPragmaHandler("omp", OpenMPMasterHandler.get());
+
+  OpenMPCriticalHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_critical, "critical"));
+  PP.AddPragmaHandler("omp", OpenMPCriticalHandler.get());
+
+  OpenMPBarrierHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_barrier, "barrier"));
+  PP.AddPragmaHandler("omp", OpenMPBarrierHandler.get());
+
+  OpenMPTaskwaitHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_taskwait, "taskwait"));
+  PP.AddPragmaHandler("omp", OpenMPTaskwaitHandler.get());
+
+  OpenMPTaskyieldHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_taskyield, "taskyield"));
+  PP.AddPragmaHandler("omp", OpenMPTaskyieldHandler.get());
+
+  OpenMPAtomicHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_atomic, "atomic"));
+  PP.AddPragmaHandler("omp", OpenMPAtomicHandler.get());
+
+  OpenMPFlushHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_flush, "flush"));
+  PP.AddPragmaHandler("omp", OpenMPFlushHandler.get());
+
+  OpenMPOrderedHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_ordered, "ordered"));
+  PP.AddPragmaHandler("omp", OpenMPOrderedHandler.get());
+
+  OpenMPThreadPrivateHandler.reset(new PragmaOmpHandler(
+                   tok::annot_pragma_omp_threadprivate, "threadprivate"));
+  PP.AddPragmaHandler("omp", OpenMPThreadPrivateHandler.get());
 }
 
 /// If a crash happens while the parser is active, print out a line indicating
@@ -456,6 +518,38 @@
 
   PP.clearCodeCompletionHandler();
 
+  // Remove the "#pragma omp ..." handlers we installed.
+  PP.RemovePragmaHandler("omp", OpenMPParallelHandler.get());
+  OpenMPParallelHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPForHandler.get());
+  OpenMPForHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPSectionsHandler.get());
+  OpenMPSectionsHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPSectionHandler.get());
+  OpenMPSectionHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPSingleHandler.get());
+  OpenMPSingleHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPTaskHandler.get());
+  OpenMPTaskHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPMasterHandler.get());
+  OpenMPMasterHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPCriticalHandler.get());
+  OpenMPCriticalHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPBarrierHandler.get());
+  OpenMPBarrierHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPTaskwaitHandler.get());
+  OpenMPTaskwaitHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPTaskyieldHandler.get());
+  OpenMPTaskyieldHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPAtomicHandler.get());
+  OpenMPAtomicHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPFlushHandler.get());
+  OpenMPFlushHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPOrderedHandler.get());
+  OpenMPOrderedHandler.reset();
+  PP.RemovePragmaHandler("omp", OpenMPThreadPrivateHandler.get());
+  OpenMPThreadPrivateHandler.reset();
+
   assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?");
 }
 
Index: test/Preprocessor/pragma_omp.c
===================================================================
--- test/Preprocessor/pragma_omp.c	(revision 0)
+++ test/Preprocessor/pragma_omp.c	(revision 0)
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -E -verify %s
+// RUN: %clang_cc1 -E -verify -fopenmp %s
+// RUN: %clang_cc1 -Eonly -verify %s
+// RUN: %clang_cc1 -Eonly -verify -fopenmp %s
+// RUN: %clang_cc1 -E -P -verify %s
+// RUN: %clang_cc1 -E -P -verify -fopenmp %s
+
+int pragma_omp_test() {
+  int i, VarA;
+  #pragma omp parallel // expected-no-diagnostics 
+  {
+    #pragma omp for    // expected-no-diagnostics 
+    for(i=0; i<10; i++) {
+      VarA = 29;
+    }
+  }
+  return VarA;
+}
Index: test/Preprocessor/pragma_omp_ignored_warning.c
===================================================================
--- test/Preprocessor/pragma_omp_ignored_warning.c	(revision 0)
+++ test/Preprocessor/pragma_omp_ignored_warning.c	(revision 0)
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int pragma_omp_ignored_warning_test() {
+  int i, VarA;
+  #pragma omp parallel // expected-warning {{pragma omp ignored; did you forget to add '-fopenmp' flag?}}
+  {
+    #pragma omp for    
+    for(i=0; i<10; i++) {
+      VarA = 29;
+    }
+  }
+  return VarA;
+}
