]> granicus.if.org Git - clang/commitdiff
Disallow using function parameters in extended asm inputs or outputs in naked functio...
authorHans Wennborg <hans@hanshq.net>
Wed, 8 Oct 2014 01:58:02 +0000 (01:58 +0000)
committerHans Wennborg <hans@hanshq.net>
Wed, 8 Oct 2014 01:58:02 +0000 (01:58 +0000)
Clang won't emit any prologues for such functions, so it would assert trying to
codegen the parameter references.

This patch makes Clang check the extended asm inputs and outputs for
references to function parameters.

Differential Revision: http://reviews.llvm.org/D5640

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

lib/Sema/SemaStmtAsm.cpp
test/Sema/attr-naked.c

index dc50e87b589b9296ab2e01f801d3137c6161696a..7f79a05b46d16b9de8a84a38041ecaed75ed5a67 100644 (file)
@@ -75,6 +75,32 @@ static bool isOperandMentioned(unsigned OpNo,
   return false;
 }
 
+static bool CheckNakedParmReference(Expr *E, Sema &S) {
+  FunctionDecl *Func = dyn_cast<FunctionDecl>(S.CurContext);
+  if (!Func)
+    return false;
+  if (!Func->hasAttr<NakedAttr>())
+    return false;
+
+  SmallVector<Expr*, 4> WorkList;
+  WorkList.push_back(E);
+  while (WorkList.size()) {
+    Expr *E = WorkList.pop_back_val();
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+      if (isa<ParmVarDecl>(DRE->getDecl())) {
+        S.Diag(DRE->getLocStart(), diag::err_asm_naked_parm_ref);
+        S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
+        return true;
+      }
+    }
+    for (Stmt *Child : E->children()) {
+      if (Expr *E = dyn_cast_or_null<Expr>(Child))
+        WorkList.push_back(E);
+    }
+  }
+  return false;
+}
+
 StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                                  bool IsVolatile, unsigned NumOutputs,
                                  unsigned NumInputs, IdentifierInfo **Names,
@@ -117,6 +143,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                             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();
@@ -160,6 +190,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
 
     Expr *InputExpr = Exprs[i];
 
+    // Referring to parameters is not allowed in naked functions.
+    if (CheckNakedParmReference(InputExpr, *this))
+      return StmtError();
+
     // Only allow void types for memory constraints.
     if (Info.allowsMemory() && !Info.allowsRegister()) {
       if (CheckAsmLValue(InputExpr, *this))
@@ -421,17 +455,8 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
   if (!Result.isUsable()) return Result;
 
   // Referring to parameters is not allowed in naked functions.
-  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Result.get())) {
-    if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
-      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Parm->getDeclContext())) {
-        if (Func->hasAttr<NakedAttr>()) {
-          Diag(Id.getLocStart(), diag::err_asm_naked_parm_ref);
-          Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
-          return ExprError();
-        }
-      }
-    }
-  }
+  if (CheckNakedParmReference(Result.get(), *this))
+    return ExprError();
 
   QualType T = Result.get()->getType();
 
index fcae842775e0db245402edfefae90618db514c25..6b1344a9860bcf499a2cbb69f1d2c9693066738b 100644 (file)
@@ -32,3 +32,19 @@ __attribute__((naked)) void t7() {
   asm("movl $42, %eax");
   ;
 }
+
+extern int x, y;
+
+__attribute__((naked)) void t8(int z) { // expected-note{{attribute is here}}
+  __asm__ ("movl $42, %1"
+           : "=r"(x),
+             "=r"(z) // expected-error{{parameter references not allowed in naked functions}}
+           );
+}
+
+__attribute__((naked)) void t9(int z) { // expected-note{{attribute is here}}
+  __asm__ ("movl %eax, %1"
+           : : "r"(x),
+               "r"(z) // expected-error{{parameter references not allowed in naked functions}}
+           );
+}