]> granicus.if.org Git - clang/commitdiff
Ensure Target Features always_inline error happens in C++ cases.
authorErich Keane <erich.keane@intel.com>
Fri, 21 Jun 2019 22:29:32 +0000 (22:29 +0000)
committerErich Keane <erich.keane@intel.com>
Fri, 21 Jun 2019 22:29:32 +0000 (22:29 +0000)
A handful of C++ cases as reported in PR42352 didn't actually give an
error when always_inlining with a different target feature list. This
resulted in broken IR.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@364109 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCall.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenCXX/target-builtin-error.o [new file with mode: 0644]
test/CodeGenCXX/target-features-error.cpp [new file with mode: 0644]

index 7b57f0848229917cbcd353a3f20cbeca9f76a857..705998d3b21613a095d19cfa57c1399bb20a48cd 100644 (file)
@@ -3791,6 +3791,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
   llvm::FunctionType *IRFuncTy = getTypes().GetFunctionType(CallInfo);
 
   const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl();
+  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
+    // We can only guarantee that a function is called from the correct
+    // context/function based on the appropriate target attributes,
+    // so only check in the case where we have both always_inline and target
+    // since otherwise we could be making a conditional call after a check for
+    // the proper cpu features (and it won't cause code generation issues due to
+    // function based code generation).
+    if (TargetDecl->hasAttr<AlwaysInlineAttr>() &&
+        TargetDecl->hasAttr<TargetAttr>())
+      checkTargetFeatures(Loc, FD);
 
 #ifndef NDEBUG
   if (!(CallInfo.isVariadic() && CallInfo.getArgStruct())) {
index 17bb9e937bb5149b40031784d3620078977963ad..c2330e0844bae540873fb7125a6d82da6b511bed 100644 (file)
@@ -4697,17 +4697,6 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
   const Decl *TargetDecl =
       OrigCallee.getAbstractInfo().getCalleeDecl().getDecl();
 
-  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
-    // We can only guarantee that a function is called from the correct
-    // context/function based on the appropriate target attributes,
-    // so only check in the case where we have both always_inline and target
-    // since otherwise we could be making a conditional call after a check for
-    // the proper cpu features (and it won't cause code generation issues due to
-    // function based code generation).
-    if (TargetDecl->hasAttr<AlwaysInlineAttr>() &&
-        TargetDecl->hasAttr<TargetAttr>())
-      checkTargetFeatures(E, FD);
-
   CalleeType = getContext().getCanonicalType(CalleeType);
 
   auto PointeeType = cast<PointerType>(CalleeType)->getPointeeType();
index 581bbe5efafffd707a54b632fbcbd0a940203997..937648700a2e8393c185eb1af46a9d3fecb0eebc 100644 (file)
@@ -2179,6 +2179,13 @@ static bool hasRequiredFeatures(const SmallVectorImpl<StringRef> &ReqFeatures,
 // called function.
 void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
                                           const FunctionDecl *TargetDecl) {
+  return checkTargetFeatures(E->getBeginLoc(), TargetDecl);
+}
+
+// Emits an error if we don't have a valid set of target features for the
+// called function.
+void CodeGenFunction::checkTargetFeatures(SourceLocation Loc,
+                                          const FunctionDecl *TargetDecl) {
   // Early exit if this is an indirect call.
   if (!TargetDecl)
     return;
@@ -2203,7 +2210,7 @@ void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
       return;
     StringRef(FeatureList).split(ReqFeatures, ',');
     if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
-      CGM.getDiags().Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
+      CGM.getDiags().Report(Loc, diag::err_builtin_needs_feature)
           << TargetDecl->getDeclName()
           << CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
 
@@ -2229,7 +2236,7 @@ void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
         ReqFeatures.push_back(F.getKey());
     }
     if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
-      CGM.getDiags().Report(E->getBeginLoc(), diag::err_function_needs_feature)
+      CGM.getDiags().Report(Loc, diag::err_function_needs_feature)
           << FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature;
   }
 }
index 3516e842ddc9c98fbcf65cdba423b179c889835b..b039d7da1f0ee58f724c08e680e4c08be436f1eb 100644 (file)
@@ -3605,6 +3605,7 @@ public:
   CGCallee EmitCallee(const Expr *E);
 
   void checkTargetFeatures(const CallExpr *E, const FunctionDecl *TargetDecl);
+  void checkTargetFeatures(SourceLocation Loc, const FunctionDecl *TargetDecl);
 
   llvm::CallInst *EmitRuntimeCall(llvm::FunctionCallee callee,
                                   const Twine &name = "");
diff --git a/test/CodeGenCXX/target-builtin-error.o b/test/CodeGenCXX/target-builtin-error.o
new file mode 100644 (file)
index 0000000..10da31e
Binary files /dev/null and b/test/CodeGenCXX/target-builtin-error.o differ
diff --git a/test/CodeGenCXX/target-features-error.cpp b/test/CodeGenCXX/target-features-error.cpp
new file mode 100644 (file)
index 0000000..44179de
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o -
+
+struct S {
+  __attribute__((always_inline, target("avx512f")))
+  void foo(){}
+  __attribute__((always_inline, target("avx512f")))
+  operator int(){ return 0; }
+  __attribute__((always_inline, target("avx512f")))
+  void operator()(){ }
+
+};
+
+void usage(S & s) {
+  s.foo(); // expected-error {{'foo' requires target feature 'avx512f'}}
+  (void)(int)s; // expected-error {{'operator int' requires target feature 'avx512f'}}
+  s(); // expected-error {{'operator()' requires target feature 'avx512f'}}
+}