[OPENMP 4.1] Allow to use 'uval' and 'ref' modifiers for reference types only.
Standard allows to use 'uval' and 'ref' modifiers in 'linear' clause for variables with reference types only. Added check for it and modified test.

llvm-svn: 245556
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1debbc5..43a51f4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7669,6 +7669,8 @@
   "parent region for 'omp %select{cancellation point/cancel}0' construct cannot be ordered">;
 def err_omp_wrong_linear_modifier : Error<
   "expected %select{'val' modifier|one of 'ref', val' or 'uval' modifiers}0">;
+def err_omp_wrong_linear_modifier_non_reference : Error<
+  "variable of non-reference type %0 can be used only with 'val' modifier, but used with '%1'">;
 } // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index e7966d4..beb38e1 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -785,9 +785,8 @@
   } else if (Kind == OMPC_linear) {
     // Try to parse modifier if any.
     if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
-      StringRef TokSpelling = PP.getSpelling(Tok);
       LinearModifier = static_cast<OpenMPLinearClauseKind>(
-          getOpenMPSimpleClauseType(Kind, TokSpelling));
+          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
       DepLinLoc = ConsumeToken();
       LinearT.consumeOpen();
       NeedRParenForLinear = true;
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 33bc621..d2653b7 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -6383,6 +6383,12 @@
                             diag::err_omp_linear_incomplete_type)) {
       continue;
     }
+    if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
+        !QType->isReferenceType()) {
+      Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
+          << QType << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
+      continue;
+    }
     QType = QType.getNonReferenceType();
 
     // A list item must not be const-qualified.
diff --git a/clang/test/OpenMP/simd_linear_messages.cpp b/clang/test/OpenMP/simd_linear_messages.cpp
index 1c6d854..792f78a 100644
--- a/clang/test/OpenMP/simd_linear_messages.cpp
+++ b/clang/test/OpenMP/simd_linear_messages.cpp
@@ -135,11 +135,11 @@
   for (int k = 0; k < argc; ++k) ++k;
   #pragma omp simd linear (argv[1]) // expected-error {{expected variable name}}
   for (int k = 0; k < argc; ++k) ++k;
-  #pragma omp simd linear(ref(e, g))
+  #pragma omp simd linear(ref(e, g)) // expected-error 2 {{variable of non-reference type 'int' can be used only with 'val' modifier, but used with 'ref'}}
   for (int k = 0; k < argc; ++k) ++k;
   #pragma omp simd linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
   for (int k = 0; k < argc; ++k) ++k;
-  #pragma omp simd linear(uval(i))
+  #pragma omp simd linear(uval(i)) // expected-error {{variable of non-reference type 'int' can be used only with 'val' modifier, but used with 'uval'}}
   for (int k = 0; k < argc; ++k) ++k;
   #pragma omp parallel
   {
@@ -148,7 +148,9 @@
     #pragma omp simd linear(v:i)
     for (int k = 0; k < argc; ++k) { i = k; v += i; }
   }
-  #pragma omp simd linear(j)
+  #pragma omp simd linear(ref(j))
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp simd linear(uval(j))
   for (int k = 0; k < argc; ++k) ++k;
   int v = 0;
   #pragma omp simd linear(v:j)
@@ -167,7 +169,7 @@
 }
 
 void linear_modifiers(int argc) {
-  int f;
+  int &f = argc;
   #pragma omp simd linear(f)
   for (int k = 0; k < argc; ++k) ++k;
   #pragma omp simd linear(val(f))
@@ -233,7 +235,7 @@
     int i;
     #pragma omp simd linear(val(i))
     for (int k = 0; k < argc; ++k) ++k;
-    #pragma omp simd linear(uval(i) : 4)
+    #pragma omp simd linear(uval(i) : 4) // expected-error {{variable of non-reference type 'int' can be used only with 'val' modifier, but used with 'uval'}}
     for (int k = 0; k < argc; ++k) { ++k; i += 4; }
   }
   #pragma omp simd linear(ref(j))
@@ -241,7 +243,7 @@
   #pragma omp simd linear(i)
   for (int k = 0; k < argc; ++k) ++k;
 
-  foomain<int,char>(argc,argv);
+  foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
   return 0;
 }