[cfe-commits] r46941 - in /cfe/trunk: CodeGen/CGExprConstant.cpp CodeGen/CodeGenModule.cpp CodeGen/CodeGenModule.h Sema/SemaExpr.cpp include/clang/AST/Expr.h test/Sema/argument-checking.m test/Sema/array-init.c test/Sema/compound-literal.c test/Sema/i-c-e2.c

Chris Lattner sabre at nondot.org
Sun Feb 10 16:02:17 PST 2008


Author: lattner
Date: Sun Feb 10 18:02:17 2008
New Revision: 46941

URL: http://llvm.org/viewvc/llvm-project?rev=46941&view=rev
Log:
Fix PR1992 by computing the right type for string literals, which
is an array type not a pointer type.  This requires updating some
diags that change and updating the code generator to handle the
proper form of strings.



Modified:
    cfe/trunk/CodeGen/CGExprConstant.cpp
    cfe/trunk/CodeGen/CodeGenModule.cpp
    cfe/trunk/CodeGen/CodeGenModule.h
    cfe/trunk/Sema/SemaExpr.cpp
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/test/Sema/argument-checking.m
    cfe/trunk/test/Sema/array-init.c
    cfe/trunk/test/Sema/compound-literal.c
    cfe/trunk/test/Sema/i-c-e2.c

Modified: cfe/trunk/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CGExprConstant.cpp?rev=46941&r1=46940&r2=46941&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/CodeGen/CGExprConstant.cpp Sun Feb 10 18:02:17 2008
@@ -205,9 +205,7 @@
       // Note that VLAs can't exist for global variables.
       // The only thing that can have array type like this is a
       // DeclRefExpr(FileVarDecl)?
-      const DeclRefExpr *DRE = cast<DeclRefExpr>(ICExpr->getSubExpr());
-      const VarDecl *VD = cast<VarDecl>(DRE->getDecl());
-      llvm::Constant *C = CGM.GetAddrOfGlobalVar(VD, false);
+      llvm::Constant *C = EmitLValue(ICExpr->getSubExpr());
       assert(isa<llvm::PointerType>(C->getType()) &&
              isa<llvm::ArrayType>(cast<llvm::PointerType>(C->getType())
                                   ->getElementType()));
@@ -232,11 +230,7 @@
   llvm::Constant *VisitStringLiteral(StringLiteral *E) {
     const char *StrData = E->getStrData();
     unsigned Len = E->getByteLength();
-    
-    // If the string has a pointer type, emit it as a global and use the pointer
-    // to the global as its value.
-    if (E->getType()->isPointerType()) 
-      return CGM.GetAddrOfConstantString(std::string(StrData, StrData + Len));
+    assert(!E->getType()->isPointerType() && "Strings are always arrays");
     
     // Otherwise this must be a string initializing an array in a static
     // initializer.  Don't emit it as the address of the string, emit the string
@@ -532,7 +526,7 @@
       // to be the only use of the variable, so we just generate it here.
       CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
       llvm::Constant* C = Visit(CLE->getInitializer());
-      C = new llvm::GlobalVariable(C->getType(), E->getType().isConstQualified(), 
+      C = new llvm::GlobalVariable(C->getType(),E->getType().isConstQualified(), 
                                    llvm::GlobalValue::InternalLinkage,
                                    C, ".compoundliteral", &CGM.getModule());
       return C;
@@ -541,8 +535,8 @@
       ValueDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
       if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
         return CGM.GetAddrOfFunctionDecl(FD, false);
-      if (const FileVarDecl* FVD = dyn_cast<FileVarDecl>(Decl))
-        return CGM.GetAddrOfGlobalVar(FVD, false);
+      if (const VarDecl* VD = dyn_cast<VarDecl>(Decl))
+        return CGM.GetAddrOfGlobalVar(VD, false);
       // We can end up here with static block-scope variables (and others?)
       // FIXME: How do we implement block-scope variables?!
       assert(0 && "Unimplemented Decl type");

Modified: cfe/trunk/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenModule.cpp?rev=46941&r1=46940&r2=46941&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenModule.cpp Sun Feb 10 18:02:17 2008
@@ -384,7 +384,7 @@
   return GV;
 }
 
-/// GenerateWritableString -- Creates storage for a string literal
+/// GenerateWritableString -- Creates storage for a string literal.
 static llvm::Constant *GenerateStringLiteral(const std::string &str, 
                                              bool constant,
                                              CodeGenModule &CGM) {
@@ -395,14 +395,11 @@
   C = new llvm::GlobalVariable(C->getType(), constant, 
                                llvm::GlobalValue::InternalLinkage,
                                C, ".str", &CGM.getModule());
-  llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
-  llvm::Constant *Zeros[] = { Zero, Zero };
-  C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
   return C;
 }
 
-/// CodeGenModule::GetAddrOfConstantString -- returns a pointer to the first 
-/// element of a character array containing the literal.
+/// CodeGenModule::GetAddrOfConstantString -- returns a pointer to the character
+/// array containing the literal.  The result is pointer to array type.
 llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str) {
   // Don't share any string literals if writable-strings is turned on.
   if (Features.WritableStrings)

Modified: cfe/trunk/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenModule.h?rev=46941&r1=46940&r2=46941&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/CodeGen/CodeGenModule.h Sun Feb 10 18:02:17 2008
@@ -80,6 +80,9 @@
   ///
   llvm::Function *getBuiltinLibFunction(unsigned BuiltinID);
   llvm::Constant *GetAddrOfConstantCFString(const std::string& str);
+
+  /// GetAddrOfConstantString -- returns a pointer to the character
+  /// array containing the literal.  The result is pointer to array type.
   llvm::Constant *GetAddrOfConstantString(const std::string& str);
   llvm::Function *getMemCpyFn();
   llvm::Function *getIntrinsic(unsigned IID, const llvm::Type **Tys = 0, 

Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=46941&r1=46940&r2=46941&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Sun Feb 10 18:02:17 2008
@@ -42,23 +42,27 @@
   llvm::SmallVector<SourceLocation, 4> StringTokLocs;
   for (unsigned i = 0; i != NumStringToks; ++i)
     StringTokLocs.push_back(StringToks[i].getLocation());
-  
-  // FIXME: handle wchar_t
-  QualType t;
-  
-  if (Literal.Pascal) 
-    t = Context.getPointerType(Context.UnsignedCharTy);
-  else
-    t = Context.getPointerType(Context.CharTy);
-  
+
+  // Verify that pascal strings aren't too large.
   if (Literal.Pascal && Literal.GetStringLength() > 256)
     return Diag(StringToks[0].getLocation(), diag::err_pascal_string_too_long,
                 SourceRange(StringToks[0].getLocation(),
                             StringToks[NumStringToks-1].getLocation()));
   
+  QualType StrTy = Context.CharTy;
+  // FIXME: handle wchar_t
+  if (Literal.Pascal) StrTy = Context.UnsignedCharTy;
+  
+  // Get an array type for the string, according to C99 6.4.5.  This includes
+  // the nul terminator character as well as the string length for pascal
+  // strings.
+  StrTy = Context.getConstantArrayType(StrTy,
+                                   llvm::APInt(32, Literal.GetStringLength()+1),
+                                       ArrayType::Normal, 0);
+  
   // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
   return new StringLiteral(Literal.GetString(), Literal.GetStringLength(), 
-                           Literal.AnyWide, t, 
+                           Literal.AnyWide, StrTy, 
                            StringToks[0].getLocation(),
                            StringToks[NumStringToks-1].getLocation());
 }

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=46941&r1=46940&r2=46941&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Sun Feb 10 18:02:17 2008
@@ -319,7 +319,8 @@
 /// StringLiteral - This represents a string literal expression, e.g. "foo"
 /// or L"bar" (wide strings).  The actual string is returned by getStrData()
 /// is NOT null-terminated, and the length of the string is determined by
-/// calling getByteLength().
+/// calling getByteLength().  The C type for a string is always a
+/// ConstantArrayType.
 class StringLiteral : public Expr {
   const char *StrData;
   unsigned ByteLength;

Modified: cfe/trunk/test/Sema/argument-checking.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/argument-checking.m?rev=46941&r1=46940&r2=46941&view=diff

==============================================================================
--- cfe/trunk/test/Sema/argument-checking.m (original)
+++ cfe/trunk/test/Sema/argument-checking.m Sun Feb 10 18:02:17 2008
@@ -17,7 +17,7 @@
   struct S sInst;
 
   charStarFunc(1); // expected-warning {{incompatible integer to pointer conversion passing 'int', expected 'char *'}}
-  charFunc("abc"); // expected-warning {{incompatible pointer to integer conversion passing 'char *', expected 'char'}}
+  charFunc("abc"); // expected-warning {{incompatible pointer to integer conversion passing 'char [4]', expected 'char'}}
 
   [obj charStarMeth:1]; // expected-warning {{incompatible integer to pointer conversion sending 'int'}}
   [obj structMeth:1]; // expected-error {{incompatible type sending 'int'}}

Modified: cfe/trunk/test/Sema/array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=46941&r1=46940&r2=46941&view=diff

==============================================================================
--- cfe/trunk/test/Sema/array-init.c (original)
+++ cfe/trunk/test/Sema/array-init.c Sun Feb 10 18:02:17 2008
@@ -9,7 +9,7 @@
 
 extern int fileScopeExtern[3] = { 1, 3, 5 }; // expected-warning{{'extern' variable has an initializer}}
 
-static int ary3[] = { 1, "abc", 3, 4 }; // expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'int'}}
+static int ary3[] = { 1, "abc", 3, 4 }; // expected-warning{{incompatible pointer to integer conversion initializing 'char [4]', expected 'int'}}
 
 void func() {
   int x = 1;
@@ -48,7 +48,7 @@
   
   extern int blockScopeExtern[3] = { 1, 3, 5 }; // expected-error{{'extern' variable cannot have an initializer}}
   
-  static int x2[3] = { 1.0, "abc" , 5.8 }; // expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'int'}}
+  static int x2[3] = { 1.0, "abc" , 5.8 }; // expected-warning{{incompatible pointer to integer conversion initializing 'char [4]', expected 'int'}}
 }
 
 void test() {
@@ -152,10 +152,10 @@
   char c[] = { "Hello" };
   int l[sizeof(c) == 6 ? 1 : -1];
   
-  int i[] = { "Hello "}; // expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'int'}}
+  int i[] = { "Hello "}; // expected-warning{{incompatible pointer to integer conversion initializing 'char [7]', expected 'int'}}
   char c2[] = { "Hello", "Good bye" }; //expected-error{{excess elements in char array initializer}}
 
-  int i2[1] = { "Hello" }; //expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'int'}}
+  int i2[1] = { "Hello" }; //expected-warning{{incompatible pointer to integer conversion initializing 'char [6]', expected 'int'}}
   char c3[5] = { "Hello" };
   char c4[4] = { "Hello" }; //expected-warning{{initializer-string for char array is too long}}
 
@@ -187,7 +187,7 @@
 struct s1 {char a; char b;} t1;
 struct s2 {struct s1 c;} t2 = { t1 };
 // The following is a less than great diagnostic (though it's on par with EDG).
-struct s1 t3[] = {t1, t1, "abc", 0}; //expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'char'}}
+struct s1 t3[] = {t1, t1, "abc", 0}; //expected-warning{{incompatible pointer to integer conversion initializing 'char [4]', expected 'char'}}
 int t4[sizeof t3 == 6 ? 1 : -1];
 }
 struct foo { int z; } w;

Modified: cfe/trunk/test/Sema/compound-literal.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/compound-literal.c?rev=46941&r1=46940&r2=46941&view=diff

==============================================================================
--- cfe/trunk/test/Sema/compound-literal.c (original)
+++ cfe/trunk/test/Sema/compound-literal.c Sun Feb 10 18:02:17 2008
@@ -9,7 +9,7 @@
 static int x = (int){1}; // -expected-error {{initializer element is not constant}} -expected-warning{{braces around scalar initializer}}
 
 static int *p2 = (int []){2,x}; // -expected-error {{initializer element is not constant}}
-static int *p3 = (int []){2,"x"}; // -expected-warning {{incompatible pointer to integer conversion initializing 'char *', expected 'int'}}
+static int *p3 = (int []){2,"x"}; // -expected-warning {{incompatible pointer to integer conversion initializing 'char [2]', expected 'int'}}
 
 typedef struct Test {int a;int b;} Test;
 static Test* ll = &(Test) {0,0};

Modified: cfe/trunk/test/Sema/i-c-e2.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/i-c-e2.c?rev=46941&r1=46940&r2=46941&view=diff

==============================================================================
--- cfe/trunk/test/Sema/i-c-e2.c (original)
+++ cfe/trunk/test/Sema/i-c-e2.c Sun Feb 10 18:02:17 2008
@@ -1,6 +1,16 @@
-// RUN: clang %s -fsyntax-only
+// RUN: clang %s -fsyntax-only -fpascal-strings
 
 char array[1024/(sizeof (long))];
 
 int x['\xBb' == (char) 187 ? 1: -1];
 
+// PR1992
+void func(int x)
+{
+ switch (x) {
+ case sizeof("abc"): break;
+ case sizeof("loooong"): func(4);
+ case sizeof("\ploooong"): func(4);
+ }
+}
+





More information about the cfe-commits mailing list