[clang] 0ee89c1 - [OPENMP50]Improve checks for declare variant functions compatibility.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 12 12:31:01 PST 2019


Author: Alexey Bataev
Date: 2019-12-12T15:18:19-05:00
New Revision: 0ee89c1bad8cef81725ef892d60b4aa254d84744

URL: https://github.com/llvm/llvm-project/commit/0ee89c1bad8cef81725ef892d60b4aa254d84744
DIFF: https://github.com/llvm/llvm-project/commit/0ee89c1bad8cef81725ef892d60b4aa254d84744.diff

LOG: [OPENMP50]Improve checks for declare variant functions compatibility.

Added check for functions compatibility in C and removed restriction
for functions with no prototypes in declare variant constrcut.

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/test/OpenMP/declare_variant_messages.c
    clang/test/OpenMP/declare_variant_messages.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 423ccbd293d2..c91ef356f944 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9696,10 +9696,6 @@ def warn_omp_declare_variant_after_used : Warning<
 def warn_omp_declare_variant_after_emitted : Warning<
   "'#pragma omp declare variant' cannot be applied to the function that was defined already;"
   " the original function might be used">, InGroup<SourceUsesOpenMP>;
-def err_omp_declare_variant_noproto : Error<
-  "function with '#pragma omp declare variant' must have a prototype">;
-def note_omp_declare_variant_specified_here : Note<
-  "'#pragma omp declare variant' for function specified here">;
 def err_omp_declare_variant_doesnt_support : Error<
   "'#pragma omp declare variant' does not "
   "support %select{function templates|virtual functions|"

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c25712452013..ebc919b52a49 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9828,13 +9828,15 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
     Linkage = 5,
   };
 
-  if (OldFD && !OldFD->getType()->getAs<FunctionProtoType>()) {
+  if (NoProtoDiagID.getDiagID() != 0 && OldFD &&
+      !OldFD->getType()->getAs<FunctionProtoType>()) {
     Diag(OldFD->getLocation(), NoProtoDiagID);
     Diag(NoteCausedDiagIDAt.first, NoteCausedDiagIDAt.second);
     return true;
   }
 
-  if (!NewFD->getType()->getAs<FunctionProtoType>())
+  if (NoProtoDiagID.getDiagID() != 0 &&
+      !NewFD->getType()->getAs<FunctionProtoType>())
     return Diag(NewFD->getLocation(), NoProtoDiagID);
 
   if (!TemplatesSupported &&

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index d876f04192b0..e02c1c591dff 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -23,6 +23,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/AST/TypeOrdering.h"
 #include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Scope.h"
@@ -5183,6 +5184,29 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
   return DG;
 }
 
+static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
+                         QualType NewType) {
+  assert(NewType->isFunctionProtoType() &&
+         "Expected function type with prototype.");
+  assert(FD->getType()->isFunctionNoProtoType() &&
+         "Expected function with type with no prototype.");
+  assert(FDWithProto->getType()->isFunctionProtoType() &&
+         "Expected function with prototype.");
+  // Synthesize parameters with the same types.
+  FD->setType(NewType);
+  SmallVector<ParmVarDecl *, 16> Params;
+  for (const ParmVarDecl *P : FDWithProto->parameters()) {
+    auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
+                                      SourceLocation(), nullptr, P->getType(),
+                                      /*TInfo=*/nullptr, SC_None, nullptr);
+    Param->setScopeInfo(0, Params.size());
+    Param->setImplicit();
+    Params.push_back(Param);
+  }
+
+  FD->setParams(Params);
+}
+
 Optional<std::pair<FunctionDecl *, Expr *>>
 Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
                                         Expr *VariantRef, SourceRange SR) {
@@ -5281,7 +5305,9 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
     if (ICS.isFailure()) {
       Diag(VariantRef->getExprLoc(),
            diag::err_omp_declare_variant_incompat_types)
-          << VariantRef->getType() << FnPtrType << VariantRef->getSourceRange();
+          << VariantRef->getType()
+          << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
+          << VariantRef->getSourceRange();
       return None;
     }
     VariantRefCast = PerformImplicitConversion(
@@ -5321,6 +5347,24 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
     return None;
   }
 
+  // Check if function types are compatible in C.
+  if (!LangOpts.CPlusPlus) {
+    QualType NewType =
+        Context.mergeFunctionTypes(FD->getType(), NewFD->getType());
+    if (NewType.isNull()) {
+      Diag(VariantRef->getExprLoc(),
+           diag::err_omp_declare_variant_incompat_types)
+          << NewFD->getType() << FD->getType() << VariantRef->getSourceRange();
+      return None;
+    }
+    if (NewType->isFunctionProtoType()) {
+      if (FD->getType()->isFunctionNoProtoType())
+        setPrototype(*this, FD, NewFD, NewType);
+      else if (NewFD->getType()->isFunctionNoProtoType())
+        setPrototype(*this, NewFD, FD, NewType);
+    }
+  }
+
   // Check if variant function is not marked with declare variant directive.
   if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
     Diag(VariantRef->getExprLoc(),
@@ -5381,10 +5425,9 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
 
   // Check general compatibility.
   if (areMultiversionVariantFunctionsCompatible(
-          FD, NewFD, PDiag(diag::err_omp_declare_variant_noproto),
-          PartialDiagnosticAt(
-              SR.getBegin(),
-              PDiag(diag::note_omp_declare_variant_specified_here) << SR),
+          FD, NewFD, PartialDiagnostic::NullDiagnostic(),
+          PartialDiagnosticAt(SourceLocation(),
+                              PartialDiagnostic::NullDiagnostic()),
           PartialDiagnosticAt(
               VariantRef->getExprLoc(),
               PDiag(diag::err_omp_declare_variant_doesnt_support)),

diff  --git a/clang/test/OpenMP/declare_variant_messages.c b/clang/test/OpenMP/declare_variant_messages.c
index 79ba957a520b..26507629ea37 100644
--- a/clang/test/OpenMP/declare_variant_messages.c
+++ b/clang/test/OpenMP/declare_variant_messages.c
@@ -80,12 +80,19 @@ int main();
 int b, c;
 
 int no_proto();
-
-// expected-error at +3 {{function with '#pragma omp declare variant' must have a prototype}}
-// expected-note at +1 {{'#pragma omp declare variant' for function specified here}}
 #pragma omp declare variant(no_proto) match(xxx={})
 int no_proto_too();
 
+int proto1(int);
+// expected-note at +2 {{previous declaration is here}}
+#pragma omp declare variant(proto1) match(xxx={})
+int 
diff _proto();
+// expected-error at +1 {{conflicting types for '
diff _proto'}}
+int 
diff _proto(double);
+
+#pragma omp declare variant(no_proto) match(xxx={})
+int 
diff _proto1(double);
+
 int after_use_variant(void);
 int after_use();
 int bar() {
@@ -104,12 +111,12 @@ int defined1(void);
 
 
 int 
diff _cc_variant(void);
-// expected-error at +1 {{function with '#pragma omp declare variant' has a 
diff erent calling convention}}
+// expected-error at +1 {{variant in '#pragma omp declare variant' with type 'int (void)' is incompatible with type 'int (void) __attribute__((vectorcall))'}}
 #pragma omp declare variant(
diff _cc_variant) match(xxx={})
 __vectorcall int 
diff _cc(void);
 
 int 
diff _ret_variant(void);
-// expected-error at +1 {{function with '#pragma omp declare variant' has a 
diff erent return type}}
+// expected-error at +1 {{variant in '#pragma omp declare variant' with type 'int (void)' is incompatible with type 'void (void)'}}
 #pragma omp declare variant(
diff _ret_variant) match(xxx={})
 void 
diff _ret(void);
 

diff  --git a/clang/test/OpenMP/declare_variant_messages.cpp b/clang/test/OpenMP/declare_variant_messages.cpp
index 0a87fe5a69c0..ca1e4c33d17e 100644
--- a/clang/test/OpenMP/declare_variant_messages.cpp
+++ b/clang/test/OpenMP/declare_variant_messages.cpp
@@ -131,7 +131,7 @@ void h(C *hp, C *hp2, C *hq, C *lin) {
   b = 0;
 }
 
-// expected-error at +1 {{variant in '#pragma omp declare variant' with type '<overloaded function type>' is incompatible with type 'void (*)(int *, int *, int *, int *)'}}
+// expected-error at +1 {{variant in '#pragma omp declare variant' with type '<overloaded function type>' is incompatible with type 'void (int *, int *, int *, int *)'}}
 #pragma omp declare variant(barbar <int>) match(xxx = {})
 template <>
 void h(int *hp, int *hp2, int *hq, int *lin);
@@ -153,7 +153,7 @@ int overload(void);
 
 int fn1();
 int fn1(int);
-// expected-error at +1 {{variant in '#pragma omp declare variant' with type '<overloaded function type>' is incompatible with type 'int (*)(float)'}}
+// expected-error at +1 {{variant in '#pragma omp declare variant' with type '<overloaded function type>' is incompatible with type 'int (float)'}}
 #pragma omp declare variant(fn1) match(xxx = {})
 int overload1(float);
 
@@ -201,7 +201,7 @@ auto fn_deduced3() { return 0; }
 auto fn_deduced3();
 
 auto fn_deduced_variant2() { return 0; }
-// expected-error at +1 {{variant in '#pragma omp declare variant' with type 'int ()' is incompatible with type 'float (*)()'}}
+// expected-error at +1 {{variant in '#pragma omp declare variant' with type 'int ()' is incompatible with type 'float ()'}}
 #pragma omp declare variant(fn_deduced_variant2) match(xxx = {})
 float fn_deduced2();
 
@@ -231,6 +231,8 @@ struct SpecialFuncs {
   void bar(int);
 #pragma omp declare variant(SpecialFuncs::baz) match(xxx = {})
 #pragma omp declare variant(SpecialFuncs::bar) match(xxx = {})
+// expected-error at +1 {{variant in '#pragma omp declare variant' with type 'int (*)()' is incompatible with type 'void (SpecialFuncs::*)()'}}
+#pragma omp declare variant(fn_sc_variant1) match(xxx = {})
   void foo1();
   SpecialFuncs& foo(const SpecialFuncs&);
   SpecialFuncs& bar(SpecialFuncs&&);


        


More information about the cfe-commits mailing list