[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