It should not be an error if an expression in inline-asm statements is not 
evaluatable while parsing the template, as the failure may be due to the 
presence of template paramaters, which do not have values at this stage.

This change suppresses those errors. 

If the template gets used, another check is made during instantiation, and a 
failure to evaluate at that time is reported as an error.

The test checks both: that the error during template parsing is not reported, 
and an error detectable during instantiation is reported.

http://reviews.llvm.org/D10452

Files:
  lib/Sema/SemaStmtAsm.cpp
  test/Sema/inline-asm-validate-tmpl.cpp

Index: lib/Sema/SemaStmtAsm.cpp
===================================================================
--- lib/Sema/SemaStmtAsm.cpp
+++ lib/Sema/SemaStmtAsm.cpp
@@ -255,17 +255,27 @@
                          << InputExpr->getSourceRange());
     } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
       llvm::APSInt Result;
-      if (!InputExpr->EvaluateAsInt(Result, Context))
-        return StmtError(
+     if (InputExpr->EvaluateAsInt(Result, Context)) {
+        // InputExpr is evaluatable as int. Verify that it satisfies the range
+        // constraints.
+        if (Result.slt(Info.getImmConstantMin()) ||
+            Result.sgt(Info.getImmConstantMax()))
+          return StmtError(Diag(InputExpr->getLocStart(),
+                                diag::err_invalid_asm_value_for_constraint)
+                           << Result.toString(10) << Info.getConstraintStr()
+                           << InputExpr->getSourceRange());
+      } else {
+        // InputExpr is not evaluatable as int, but we do not consider this an
+        // error if we are parsing a template, because the reason for failure
+        // may have been the presence of template parameters in the expression.
+        // If the template is used, we will come to this point again
+        // with (getTemplateParamParent()==nullptr). That will catch the error.
+        if (getCurScope()->getTemplateParamParent() == nullptr) {
+          return StmtError(
             Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
             << Info.getConstraintStr() << InputExpr->getSourceRange());
-      if (Result.slt(Info.getImmConstantMin()) ||
-          Result.sgt(Info.getImmConstantMax()))
-        return StmtError(Diag(InputExpr->getLocStart(),
-                              diag::err_invalid_asm_value_for_constraint)
-                         << Result.toString(10) << Info.getConstraintStr()
-                         << InputExpr->getSourceRange());
-
+        }
+      }
     } else {
       ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
       if (Result.isInvalid())
Index: test/Sema/inline-asm-validate-tmpl.cpp
===================================================================
--- test/Sema/inline-asm-validate-tmpl.cpp
+++ test/Sema/inline-asm-validate-tmpl.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple i686 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64 -fsyntax-only -verify %s
+
+
+// this template, when instantiated with 300, violates the range contraint
+template <int N> void  test(int value)
+{
+  asm("rol %1, %0" :"=r"(value): "I"(N + 1)); // expected-error{{value '301' 
out of range for constraint 'I'}}
+}
+
+int            main() { test<300>(10); } // expected-note{{in instantiation of 
function template specialization 'test<300>' requested here}}
+
+
+// this template is not used, but the error is detectable
+template <int N> void  testb(int value)
+{
+   asm("rol %1, %0" :"=r"(value): "I"(301)); // expected-error{{value '301' 
out of range for constraint 'I'}}
+}
+
+// these should compile without error
+template <int N> void  testc(int value)
+{
+       asm("rol %1, %0" :"=r"(value): "I"(N + 1));
+}
+int    foo() { testc<2>(10); }

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: lib/Sema/SemaStmtAsm.cpp
===================================================================
--- lib/Sema/SemaStmtAsm.cpp
+++ lib/Sema/SemaStmtAsm.cpp
@@ -255,17 +255,27 @@
                          << InputExpr->getSourceRange());
     } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
       llvm::APSInt Result;
-      if (!InputExpr->EvaluateAsInt(Result, Context))
-        return StmtError(
+     if (InputExpr->EvaluateAsInt(Result, Context)) {
+        // InputExpr is evaluatable as int. Verify that it satisfies the range
+        // constraints.
+        if (Result.slt(Info.getImmConstantMin()) ||
+            Result.sgt(Info.getImmConstantMax()))
+          return StmtError(Diag(InputExpr->getLocStart(),
+                                diag::err_invalid_asm_value_for_constraint)
+                           << Result.toString(10) << Info.getConstraintStr()
+                           << InputExpr->getSourceRange());
+      } else {
+        // InputExpr is not evaluatable as int, but we do not consider this an
+        // error if we are parsing a template, because the reason for failure
+        // may have been the presence of template parameters in the expression.
+        // If the template is used, we will come to this point again
+        // with (getTemplateParamParent()==nullptr). That will catch the error.
+        if (getCurScope()->getTemplateParamParent() == nullptr) {
+          return StmtError(
             Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
             << Info.getConstraintStr() << InputExpr->getSourceRange());
-      if (Result.slt(Info.getImmConstantMin()) ||
-          Result.sgt(Info.getImmConstantMax()))
-        return StmtError(Diag(InputExpr->getLocStart(),
-                              diag::err_invalid_asm_value_for_constraint)
-                         << Result.toString(10) << Info.getConstraintStr()
-                         << InputExpr->getSourceRange());
-
+        }
+      }
     } else {
       ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
       if (Result.isInvalid())
Index: test/Sema/inline-asm-validate-tmpl.cpp
===================================================================
--- test/Sema/inline-asm-validate-tmpl.cpp
+++ test/Sema/inline-asm-validate-tmpl.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple i686 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64 -fsyntax-only -verify %s
+
+
+// this template, when instantiated with 300, violates the range contraint
+template <int N> void	test(int value)
+{
+  asm("rol %1, %0" :"=r"(value): "I"(N + 1)); // expected-error{{value '301' out of range for constraint 'I'}}
+}
+
+int		main() { test<300>(10); } // expected-note{{in instantiation of function template specialization 'test<300>' requested here}}
+
+
+// this template is not used, but the error is detectable
+template <int N> void	testb(int value)
+{
+   asm("rol %1, %0" :"=r"(value): "I"(301)); // expected-error{{value '301' out of range for constraint 'I'}}
+}
+
+// these should compile without error
+template <int N> void	testc(int value)
+{
+	asm("rol %1, %0" :"=r"(value): "I"(N + 1));
+}
+int	foo() { testc<2>(10); }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to