[cfe-commits] r66910 - in /cfe/trunk: Driver/clang.cpp include/clang/Basic/DiagnosticSemaKinds.def include/clang/Basic/LangOptions.h lib/CodeGen/CGStmt.cpp lib/Sema/SemaStmt.cpp test/Sema/heinous-extensions-off.c test/Sema/heinous-extensions-on.c

Chris Lattner sabre at nondot.org
Fri Mar 13 10:38:01 PDT 2009


Author: lattner
Date: Fri Mar 13 12:38:01 2009
New Revision: 66910

URL: http://llvm.org/viewvc/llvm-project?rev=66910&view=rev
Log:
introduce a new -fheinous-gnu-extensions flag that enables really
really horrible extensions that are disabled by default but that can
be accepted by -fheinous-gnu-extensions (but which always emit a 
warning when enabled).

As our first instance of this, implement PR3788/PR3794, which allows
non-lvalues in inline asms in contexts where lvalues are required. bleh.



Added:
    cfe/trunk/test/Sema/heinous-extensions-off.c
    cfe/trunk/test/Sema/heinous-extensions-on.c
Modified:
    cfe/trunk/Driver/clang.cpp
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/include/clang/Basic/LangOptions.h
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp

Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=66910&r1=66909&r2=66910&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Fri Mar 13 12:38:01 2009
@@ -480,6 +480,11 @@
              llvm::cl::ZeroOrMore);
 
 static llvm::cl::opt<bool>
+EnableHeinousExtensions("fheinous-gnu-extensions",
+   llvm::cl::desc("enable GNU extensions that you really really shouldn't use"),
+                        llvm::cl::ValueDisallowed, llvm::cl::Hidden);
+
+static llvm::cl::opt<bool>
 ObjCNonFragileABI("fobjc-nonfragile-abi",
                   llvm::cl::desc("enable objective-c's nonfragile abi"));
 
@@ -647,6 +652,8 @@
 
   if (Freestanding)
     Options.Freestanding = 1;
+  if (EnableHeinousExtensions)
+    Options.HeinousExtensions = 1;
 
   Options.MathErrno = MathErrno;
 

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=66910&r1=66909&r2=66910&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Fri Mar 13 12:38:01 2009
@@ -1205,6 +1205,13 @@
      "invalid type %0 in asm input for constraint '%1'")
 DIAG(err_asm_unknown_register_name, ERROR,
     "unknown register name '%0' in asm")
+DIAG(err_invalid_asm_cast_lvalue, ERROR,
+     "invalid use of a cast in a inline asm context requiring an l-value:"
+     " remove the cast or build with -fheinous-gnu-extensions")
+DIAG(warn_invalid_asm_cast_lvalue, WARNING,
+     "invalid use of a cast in a inline asm context requiring an l-value:"
+     " accepted due to -fheinous-gnu-extensions, but clang may remove support"
+     " for this in the future")
     
 DIAG(err_invalid_conversion_between_vectors, ERROR,
     "invalid conversion between vector type %0 and %1 of different size")

Modified: cfe/trunk/include/clang/Basic/LangOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=66910&r1=66909&r2=66910&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.h (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.h Fri Mar 13 12:38:01 2009
@@ -57,6 +57,8 @@
   unsigned MathErrno         : 1; // Math functions must respect errno
                                   // (modulo the platform support).
 
+  unsigned HeinousExtensions : 1; // Extensions that we really don't like and
+                                  // may be ripped out at any time.
 private:
   unsigned GC : 2; // Objective-C Garbage Collection modes.  We declare
                    // this enum as unsigned because MSVC insists on making enums
@@ -75,6 +77,7 @@
     CXXOperatorNames = PascalStrings = Boolean = WritableStrings = 0;
     Exceptions = NeXTRuntime = Freestanding = 0;
     LaxVectorConversions = 1;
+    HeinousExtensions = 0;
     
     // FIXME: The default should be 1.
     ThreadsafeStatics = 0;

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=66910&r1=66909&r2=66910&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Fri Mar 13 12:38:01 2009
@@ -730,6 +730,7 @@
     if (Ty->isSingleValueType()) {
       Arg = EmitScalarExpr(InputExpr);
     } else {
+      InputExpr = InputExpr->IgnoreParenNoopCasts(getContext());
       LValue Dest = EmitLValue(InputExpr);
 
       uint64_t Size = CGM.getTargetData().getTypeSizeInBits(Ty);
@@ -744,6 +745,7 @@
       }
     }
   } else {
+    InputExpr = InputExpr->IgnoreParenNoopCasts(getContext());
     LValue Dest = EmitLValue(InputExpr);
     Arg = Dest.getAddress();
     ConstraintStr += '*';
@@ -799,7 +801,10 @@
     // Simplify the output constraint.
     OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1, Target);
     
-    LValue Dest = EmitLValue(S.getOutputExpr(i));
+    const Expr *OutExpr = S.getOutputExpr(i);
+    OutExpr = OutExpr->IgnoreParenNoopCasts(getContext());
+    
+    LValue Dest = EmitLValue(OutExpr);
     const llvm::Type *DestValueType = 
       cast<llvm::PointerType>(Dest.getAddress()->getType())->getElementType();
     

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=66910&r1=66909&r2=66910&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Mar 13 12:38:01 2009
@@ -641,9 +641,7 @@
         return StmtError(Diag(VD->getLocation(),
                               diag::err_non_variable_decl_in_for));
     } else {
-      Expr::isLvalueResult lval = cast<Expr>(First)->isLvalue(Context);
-
-      if (lval != Expr::LV_Valid)
+      if (cast<Expr>(First)->isLvalue(Context) != Expr::LV_Valid)
         return StmtError(Diag(First->getLocStart(),
                    diag::err_selector_element_not_lvalue)
           << First->getSourceRange());
@@ -833,6 +831,36 @@
   return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp));
 }
 
+/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
+/// ignore "noop" casts in places where an lvalue is required by an inline asm.
+/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
+/// provide a strong guidance to not use it.
+///
+/// This method checks to see if the argument is an acceptable l-value and
+/// returns false if it is a case we can handle.
+static bool CheckAsmLValue(const Expr *E, Sema &S) {
+  if (E->isLvalue(S.Context) == Expr::LV_Valid)
+    return false;  // Cool, this is an lvalue.
+
+  // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
+  // are supposed to allow.
+  const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
+  if (E != E2 && E2->isLvalue(S.Context) == Expr::LV_Valid) {
+    if (!S.getLangOptions().HeinousExtensions)
+      S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
+        << E->getSourceRange();
+    else
+      S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
+        << E->getSourceRange();
+    // Accept, even if we emitted an error diagnostic.
+    return false;
+  }
+
+  // None of the above, just randomly invalid non-lvalue.
+  return true;
+}
+
+
 Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
                                           bool IsSimple,
                                           bool IsVolatile,
@@ -875,8 +903,7 @@
 
     // Check that the output exprs are valid lvalues.
     ParenExpr *OutputExpr = cast<ParenExpr>(Exprs[i]);
-    Expr::isLvalueResult Result = OutputExpr->isLvalue(Context);
-    if (Result != Expr::LV_Valid) {
+    if (CheckAsmLValue(OutputExpr, *this)) {
       return StmtError(Diag(OutputExpr->getSubExpr()->getLocStart(),
                   diag::err_asm_invalid_lvalue_in_output)
         << OutputExpr->getSubExpr()->getSourceRange());
@@ -909,7 +936,7 @@
     // Only allow void types for memory constraints.
     if ((info & TargetInfo::CI_AllowsMemory) 
         && !(info & TargetInfo::CI_AllowsRegister)) {
-      if (InputExpr->isLvalue(Context) != Expr::LV_Valid)
+      if (CheckAsmLValue(InputExpr, *this))
         return StmtError(Diag(InputExpr->getSubExpr()->getLocStart(),
                               diag::err_asm_invalid_lvalue_in_input)
           << InputConstraint << InputExpr->getSubExpr()->getSourceRange());

Added: cfe/trunk/test/Sema/heinous-extensions-off.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/heinous-extensions-off.c?rev=66910&view=auto

==============================================================================
--- cfe/trunk/test/Sema/heinous-extensions-off.c (added)
+++ cfe/trunk/test/Sema/heinous-extensions-off.c Fri Mar 13 12:38:01 2009
@@ -0,0 +1,10 @@
+// RUN: clang %s -verify
+
+int foo() {
+        int a;
+        // PR3788
+        asm("nop" : : "m"((int)(a))); // expected-error {{cast in a inline asm context requiring an l-value}}
+        // PR3794
+        asm("nop" : "=r"((unsigned)a)); // expected-error {{cast in a inline asm context requiring an l-value}}
+}
+

Added: cfe/trunk/test/Sema/heinous-extensions-on.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/heinous-extensions-on.c?rev=66910&view=auto

==============================================================================
--- cfe/trunk/test/Sema/heinous-extensions-on.c (added)
+++ cfe/trunk/test/Sema/heinous-extensions-on.c Fri Mar 13 12:38:01 2009
@@ -0,0 +1,10 @@
+// RUN: clang %s -verify -fheinous-gnu-extensions
+
+int foo() {
+        int a;
+        // PR3788
+        asm("nop" : : "m"((int)(a))); // expected-warning {{cast in a inline asm context requiring an l-value}}
+        // PR3794
+        asm("nop" : "=r"((unsigned)a)); // expected-warning {{cast in a inline asm context requiring an l-value}}
+}
+





More information about the cfe-commits mailing list