summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2019-09-13 20:18:17 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2019-09-13 20:18:17 +0000
commitd158cf64d64b6b1882fd8f09e5d8619cb8529a5f (patch)
tree2537d474e94e13ba8c98217d79e004f2bf536e27 /clang/lib/Sema/SemaDecl.cpp
parentf69c91780fbb0e9c0e95f70a079f578efdca0bfa (diff)
downloadbcm5719-llvm-d158cf64d64b6b1882fd8f09e5d8619cb8529a5f.tar.gz
bcm5719-llvm-d158cf64d64b6b1882fd8f09e5d8619cb8529a5f.zip
[OPENMP5.0]Add basic support for declare variant directive.
Added basic support for declare variant directive and its match clause with user context selector. llvm-svn: 371892
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp160
1 files changed, 85 insertions, 75 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1290c615c00..dfa5647e9df 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9670,10 +9670,13 @@ static bool HasNonMultiVersionAttributes(const FunctionDecl *FD,
return false;
}
-static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
- const FunctionDecl *NewFD,
- bool CausesMV,
- MultiVersionKind MVType) {
+bool Sema::areMultiversionVariantFunctionsCompatible(
+ const FunctionDecl *OldFD, const FunctionDecl *NewFD,
+ const PartialDiagnostic &NoProtoDiagID,
+ const PartialDiagnosticAt &NoteCausedDiagIDAt,
+ const PartialDiagnosticAt &NoSupportDiagIDAt,
+ const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported,
+ bool ConstexprSupported) {
enum DoesntSupport {
FuncTemplates = 0,
VirtFuncs = 1,
@@ -9691,123 +9694,85 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
ConstexprSpec = 2,
InlineSpec = 3,
StorageClass = 4,
- Linkage = 5
+ Linkage = 5,
};
- bool IsCPUSpecificCPUDispatchMVType =
- MVType == MultiVersionKind::CPUDispatch ||
- MVType == MultiVersionKind::CPUSpecific;
-
if (OldFD && !OldFD->getType()->getAs<FunctionProtoType>()) {
- S.Diag(OldFD->getLocation(), diag::err_multiversion_noproto);
- S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ Diag(OldFD->getLocation(), NoProtoDiagID);
+ Diag(NoteCausedDiagIDAt.first, NoteCausedDiagIDAt.second);
return true;
}
if (!NewFD->getType()->getAs<FunctionProtoType>())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_noproto);
-
- if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) {
- S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported);
- if (OldFD)
- S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
- return true;
- }
-
- // For now, disallow all other attributes. These should be opt-in, but
- // an analysis of all of them is a future FIXME.
- if (CausesMV && OldFD && HasNonMultiVersionAttributes(OldFD, MVType)) {
- S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs)
- << IsCPUSpecificCPUDispatchMVType;
- S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
- return true;
- }
+ return Diag(NewFD->getLocation(), NoProtoDiagID);
- if (HasNonMultiVersionAttributes(NewFD, MVType))
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs)
- << IsCPUSpecificCPUDispatchMVType;
-
- if (NewFD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << FuncTemplates;
+ if (!TemplatesSupported &&
+ NewFD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << FuncTemplates;
if (const auto *NewCXXFD = dyn_cast<CXXMethodDecl>(NewFD)) {
if (NewCXXFD->isVirtual())
- return S.Diag(NewCXXFD->getLocation(),
- diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << VirtFuncs;
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << VirtFuncs;
- if (const auto *NewCXXCtor = dyn_cast<CXXConstructorDecl>(NewFD))
- return S.Diag(NewCXXCtor->getLocation(),
- diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << Constructors;
+ if (isa<CXXConstructorDecl>(NewCXXFD))
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << Constructors;
- if (const auto *NewCXXDtor = dyn_cast<CXXDestructorDecl>(NewFD))
- return S.Diag(NewCXXDtor->getLocation(),
- diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << Destructors;
+ if (isa<CXXDestructorDecl>(NewCXXFD))
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << Destructors;
}
if (NewFD->isDeleted())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << DeletedFuncs;
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << DeletedFuncs;
if (NewFD->isDefaulted())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << DefaultedFuncs;
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << DefaultedFuncs;
- if (NewFD->isConstexpr() && (MVType == MultiVersionKind::CPUDispatch ||
- MVType == MultiVersionKind::CPUSpecific))
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType
+ if (!ConstexprSupported && NewFD->isConstexpr())
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
<< (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
- QualType NewQType = S.getASTContext().getCanonicalType(NewFD->getType());
+ QualType NewQType = Context.getCanonicalType(NewFD->getType());
const auto *NewType = cast<FunctionType>(NewQType);
QualType NewReturnType = NewType->getReturnType();
if (NewReturnType->isUndeducedType())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << DeducedReturn;
-
- // Only allow transition to MultiVersion if it hasn't been used.
- if (OldFD && CausesMV && OldFD->isUsed(false))
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_after_used);
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << DeducedReturn;
// Ensure the return type is identical.
if (OldFD) {
- QualType OldQType = S.getASTContext().getCanonicalType(OldFD->getType());
+ QualType OldQType = Context.getCanonicalType(OldFD->getType());
const auto *OldType = cast<FunctionType>(OldQType);
FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
if (OldTypeInfo.getCC() != NewTypeInfo.getCC())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << CallingConv;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << CallingConv;
QualType OldReturnType = OldType->getReturnType();
if (OldReturnType != NewReturnType)
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << ReturnType;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << ReturnType;
if (OldFD->getConstexprKind() != NewFD->getConstexprKind())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << ConstexprSpec;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << ConstexprSpec;
if (OldFD->isInlineSpecified() != NewFD->isInlineSpecified())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << InlineSpec;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << InlineSpec;
if (OldFD->getStorageClass() != NewFD->getStorageClass())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << StorageClass;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << StorageClass;
if (OldFD->isExternC() != NewFD->isExternC())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << Linkage;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << Linkage;
- if (S.CheckEquivalentExceptionSpec(
+ if (CheckEquivalentExceptionSpec(
OldFD->getType()->getAs<FunctionProtoType>(), OldFD->getLocation(),
NewFD->getType()->getAs<FunctionProtoType>(), NewFD->getLocation()))
return true;
@@ -9815,6 +9780,51 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
return false;
}
+static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
+ const FunctionDecl *NewFD,
+ bool CausesMV,
+ MultiVersionKind MVType) {
+ if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported);
+ if (OldFD)
+ S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
+ bool IsCPUSpecificCPUDispatchMVType =
+ MVType == MultiVersionKind::CPUDispatch ||
+ MVType == MultiVersionKind::CPUSpecific;
+
+ // For now, disallow all other attributes. These should be opt-in, but
+ // an analysis of all of them is a future FIXME.
+ if (CausesMV && OldFD && HasNonMultiVersionAttributes(OldFD, MVType)) {
+ S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs)
+ << IsCPUSpecificCPUDispatchMVType;
+ S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ return true;
+ }
+
+ if (HasNonMultiVersionAttributes(NewFD, MVType))
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs)
+ << IsCPUSpecificCPUDispatchMVType;
+
+ // Only allow transition to MultiVersion if it hasn't been used.
+ if (OldFD && CausesMV && OldFD->isUsed(false))
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_after_used);
+
+ return S.areMultiversionVariantFunctionsCompatible(
+ OldFD, NewFD, S.PDiag(diag::err_multiversion_noproto),
+ PartialDiagnosticAt(NewFD->getLocation(),
+ S.PDiag(diag::note_multiversioning_caused_here)),
+ PartialDiagnosticAt(NewFD->getLocation(),
+ S.PDiag(diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType),
+ PartialDiagnosticAt(NewFD->getLocation(),
+ S.PDiag(diag::err_multiversion_diff)),
+ /*TemplatesSupported=*/false,
+ /*ConstexprSupported=*/!IsCPUSpecificCPUDispatchMVType);
+}
+
/// Check the validity of a multiversion function declaration that is the
/// first of its kind. Also sets the multiversion'ness' of the function itself.
///
OpenPOWER on IntegriCloud