Add sema support for symbolic names in inline asm statements.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62441 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index ca755b9..da14365 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -202,7 +202,11 @@
                                const std::string *OutputNamesBegin,
                                const std::string *OutputNamesEnd,
                                ConstraintInfo &info) const;
-
+  bool resolveSymbolicName(const char *&Name,
+                           const std::string *OutputNamesBegin,
+                           const std::string *OutputNamesEnd,
+                           unsigned &Index) const;
+  
   virtual std::string convertConstraint(const char Constraint) const {
     return std::string(1, Constraint);
   }
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 2ea1f23..eb912d5 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -188,6 +188,36 @@
   return true;
 }
 
+bool TargetInfo::resolveSymbolicName(const char *&Name,
+                                     const std::string *OutputNamesBegin,
+                                     const std::string *OutputNamesEnd,
+                                     unsigned &Index) const
+{
+  assert(*Name == '[' && "Symbolic name did not start with '['");
+
+  Name++;
+  const char *Start = Name;
+  while (*Name && *Name != ']')
+    Name++;
+  
+  if (!*Name) {
+    // Missing ']'
+    return false;
+  }
+  
+  std::string SymbolicName(Start, Name - Start);
+  
+  Index = 0;
+  for (const std::string *it = OutputNamesBegin; 
+       it != OutputNamesEnd; 
+       ++it, Index++) {
+    if (SymbolicName == *it)
+      return true;
+  }
+
+  return false;
+}
+
 bool TargetInfo::validateInputConstraint(const char *Name,
                                          const std::string *OutputNamesBegin,
                                          const std::string *OutputNamesEnd,
@@ -210,7 +240,15 @@
         // add more constraints as we hit it.  Eventually, an unknown
         // constraint should just be treated as 'g'.
         return false;
-      }        
+      }
+      break;
+    case '[': {
+      unsigned Index = 0;
+      if (!resolveSymbolicName(Name, OutputNamesBegin, OutputNamesEnd, Index))
+        return false;
+    
+      break;
+    }          
     case '%': // commutative
       // FIXME: Fail if % is used with the last operand.
       break;
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index d86c3f4..04fc26d 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -980,7 +980,7 @@
                                                  S.begin_output_names(),
                                                  S.end_output_names(),
                                                  Info);
-    assert(result && "Failed to parse input constraint"); result=result;
+    assert(result && "Failed to parse input constraint");
     
     if (i != 0 || S.getNumOutputs() > 0)
       Constraints += ',';
diff --git a/test/Sema/asm.c b/test/Sema/asm.c
index d29335a..3bb7d78 100644
--- a/test/Sema/asm.c
+++ b/test/Sema/asm.c
@@ -10,7 +10,11 @@
   
   asm ("foo\n" : "=a" (f())); // expected-error {{invalid lvalue in asm output}}
   asm ("foo\n" : "=a" (i + 2)); // expected-error {{invalid lvalue in asm output}}
-  
+
+  asm ("foo\n" : [symbolic_name] "=a" (i) : "[symbolic_name]" (i));
+  asm ("foo\n" : "=a" (i) : "[" (i)); // expected-error {{invalid input constraint '[' in asm}}
+  asm ("foo\n" : "=a" (i) : "[foo" (i)); // expected-error {{invalid input constraint '[foo' in asm}}
+  asm ("foo\n" : "=a" (i) : "[symbolic_name]" (i)); // expected-error {{invalid input constraint '[symbolic_name]' in asm}}
 }
 
 void