r224916 - Sema: Only permit permit modifiable l-values as asm output params

David Majnemer david.majnemer at gmail.com
Mon Dec 29 01:30:33 PST 2014


Author: majnemer
Date: Mon Dec 29 03:30:33 2014
New Revision: 224916

URL: http://llvm.org/viewvc/llvm-project?rev=224916&view=rev
Log:
Sema: Only permit permit modifiable l-values as asm output params

Functions are l-values in C++ but shouldn't be available as output
parameters in inline assembly.  Neither should overloaded function
l-values.

This fixes PR21949.

Modified:
    cfe/trunk/lib/Sema/SemaStmtAsm.cpp
    cfe/trunk/test/SemaCXX/statements.cpp

Modified: cfe/trunk/lib/Sema/SemaStmtAsm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAsm.cpp?rev=224916&r1=224915&r2=224916&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmtAsm.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmtAsm.cpp Mon Dec 29 03:30:33 2014
@@ -132,31 +132,54 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceL
                             diag::err_asm_invalid_output_constraint)
                        << Info.getConstraintStr());
 
+    ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
+    if (ER.isInvalid())
+      return StmtError();
+    Exprs[i] = ER.get();
+
     // Check that the output exprs are valid lvalues.
     Expr *OutputExpr = Exprs[i];
-    if (CheckAsmLValue(OutputExpr, *this))
-      return StmtError(Diag(OutputExpr->getLocStart(),
-                            diag::err_asm_invalid_lvalue_in_output)
-                       << OutputExpr->getSourceRange());
 
     // Referring to parameters is not allowed in naked functions.
     if (CheckNakedParmReference(OutputExpr, *this))
       return StmtError();
 
-    if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
-                            diag::err_dereference_incomplete_type))
-      return StmtError();
-
     OutputConstraintInfos.push_back(Info);
 
-    const Type *Ty = OutputExpr->getType().getTypePtr();
-
-    // If this is a dependent type, just continue. We don't know the size of a
-    // dependent type.
-    if (Ty->isDependentType())
+    // If this is dependent, just continue.
+    if (OutputExpr->isTypeDependent())
       continue;
 
-    unsigned Size = Context.getTypeSize(Ty);
+    Expr::isModifiableLvalueResult IsLV =
+        OutputExpr->isModifiableLvalue(Context, /*Loc=*/nullptr);
+    switch (IsLV) {
+    case Expr::MLV_Valid:
+      // Cool, this is an lvalue.
+      break;
+    case Expr::MLV_LValueCast: {
+      const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context);
+      if (!getLangOpts().HeinousExtensions) {
+        Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue)
+            << OutputExpr->getSourceRange();
+      } else {
+        Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
+            << OutputExpr->getSourceRange();
+      }
+      // Accept, even if we emitted an error diagnostic.
+      break;
+    }
+    case Expr::MLV_IncompleteType:
+    case Expr::MLV_IncompleteVoidType:
+      if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
+                              diag::err_dereference_incomplete_type))
+        return StmtError();
+    default:
+      return StmtError(Diag(OutputExpr->getLocStart(),
+                            diag::err_asm_invalid_lvalue_in_output)
+                       << OutputExpr->getSourceRange());
+    }
+
+    unsigned Size = Context.getTypeSize(OutputExpr->getType());
     if (!Context.getTargetInfo().validateOutputSize(Literal->getString(),
                                                     Size))
       return StmtError(Diag(OutputExpr->getLocStart(),
@@ -182,6 +205,11 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceL
                        << Info.getConstraintStr());
     }
 
+    ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
+    if (ER.isInvalid())
+      return StmtError();
+    Exprs[i] = ER.get();
+
     Expr *InputExpr = Exprs[i];
 
     // Referring to parameters is not allowed in naked functions.

Modified: cfe/trunk/test/SemaCXX/statements.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/statements.cpp?rev=224916&r1=224915&r2=224916&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/statements.cpp (original)
+++ cfe/trunk/test/SemaCXX/statements.cpp Mon Dec 29 03:30:33 2014
@@ -20,3 +20,13 @@ namespace PR6536 {
   struct A {};
   void a() { goto out; A x; out: return; }
 }
+
+void test3() {
+    __asm__ ("":"+r" (test3)); // expected-error{{invalid lvalue in asm output}}
+}
+
+void test4();                // expected-note{{possible target for call}}
+void test4(int) {            // expected-note{{possible target for call}}
+  // expected-error at +1{{overloaded function could not be resolved}}
+  __asm__ ("":"+r" (test4)); // expected-error{{invalid lvalue in asm output}}
+}





More information about the cfe-commits mailing list