[cfe-commits] r41136 - in /cfe/trunk: AST/ASTContext.cpp AST/Builtins.cpp Sema/Sema.h Sema/SemaChecking.cpp Sema/SemaExpr.cpp include/clang/AST/ASTContext.h include/clang/AST/Builtins.def include/clang/Basic/DiagnosticKinds.def test/Sema/cfstring.c

Anders Carlsson andersca at mac.com
Thu Aug 16 22:31:47 PDT 2007


Author: andersca
Date: Fri Aug 17 00:31:46 2007
New Revision: 41136

URL: http://llvm.org/viewvc/llvm-project?rev=41136&view=rev
Log:
Add initial support for constant CFStrings.

Added:
    cfe/trunk/test/Sema/cfstring.c
Modified:
    cfe/trunk/AST/ASTContext.cpp
    cfe/trunk/AST/Builtins.cpp
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaChecking.cpp
    cfe/trunk/Sema/SemaExpr.cpp
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Builtins.def
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def

Modified: cfe/trunk/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/ASTContext.cpp?rev=41136&r1=41135&r2=41136&view=diff

==============================================================================
--- cfe/trunk/AST/ASTContext.cpp (original)
+++ cfe/trunk/AST/ASTContext.cpp Fri Aug 17 00:31:46 2007
@@ -740,3 +740,32 @@
     return signedType; 
   }
 }
+
+// getCFConstantStringType - Return the type used for constant CFStrings. 
+QualType ASTContext::getCFConstantStringType() {
+  if (!CFConstantStringTypeDecl) {
+    CFConstantStringTypeDecl = new RecordDecl(Decl::Struct, SourceLocation(), 
+                                              &Idents.get("__builtin_CFString"), 
+                                              0);
+  
+    QualType FieldTypes[4];
+  
+    // const int *isa;
+    FieldTypes[0] = getPointerType(IntTy.getQualifiedType(QualType::Const));  
+    // int flags;
+    FieldTypes[1] = IntTy;  
+    // const char *str;
+    FieldTypes[2] = getPointerType(CharTy.getQualifiedType(QualType::Const));  
+    // long length;
+    FieldTypes[3] = LongTy;  
+    // Create fields
+    FieldDecl *FieldDecls[4];
+  
+    for (unsigned i = 0; i < 4; ++i)
+      FieldDecls[i] = new FieldDecl(SourceLocation(), 0, FieldTypes[i], 0);
+  
+    CFConstantStringTypeDecl->defineBody(FieldDecls, 4);
+  }
+  
+  return getTagDeclType(CFConstantStringTypeDecl);
+}

Modified: cfe/trunk/AST/Builtins.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Builtins.cpp?rev=41136&r1=41135&r2=41136&view=diff

==============================================================================
--- cfe/trunk/AST/Builtins.cpp (original)
+++ cfe/trunk/AST/Builtins.cpp Fri Aug 17 00:31:46 2007
@@ -84,34 +84,71 @@
     }
   }
 
+  QualType Type;
+  
   // Read the base type.
   switch (*Str++) {
   default: assert(0 && "Unknown builtin type letter!");
   case 'v':
     assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'v'!");
-    return Context.VoidTy;
+    Type = Context.VoidTy;
+    break;
   case 'f':
     assert(!Long && !Signed && !Unsigned && "Bad modifiers used with 'f'!");
-    return Context.FloatTy;
+    Type = Context.FloatTy;
+    break;
   case 'd':
     assert(!LongLong && !Signed && !Unsigned && "Bad modifiers used with 'd'!");
     if (Long)
-      return Context.LongDoubleTy;
-    return Context.DoubleTy;
+      Type = Context.LongDoubleTy;
+    else
+      Type = Context.DoubleTy;
+    break;
   case 's':
     assert(!LongLong && "Bad modifiers used with 's'!");
     if (Unsigned)
-      return Context.UnsignedShortTy;
-    return Context.ShortTy;
+      Type = Context.UnsignedShortTy;
+    else
+      Type = Context.ShortTy;
+      break;
   case 'i':
     if (Long)
-      return Unsigned ? Context.UnsignedLongTy : Context.LongTy;
-    if (LongLong)
-      return Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
-    if (Unsigned)
-      return Context.UnsignedIntTy;
-    return Context.IntTy; // default is signed.
+      Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy;
+    else if (LongLong)
+      Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
+    else if (Unsigned)
+      Type = Context.UnsignedIntTy;
+    else 
+      Type = Context.IntTy; // default is signed.
+    break;
+  case 'c':
+    assert(!Long && !LongLong && "Bad modifiers used with 'c'!");
+    if (Signed)
+      Type = Context.SignedCharTy;
+    else if (Unsigned)
+      Type = Context.UnsignedCharTy;
+    else
+      Type = Context.CharTy;
+    break;
+  case 'F':
+    Type = Context.getCFConstantStringType();
+    break;
+  }
+  
+  Done = false;
+  while (!Done) {
+    switch (*Str++) {
+      default: Done = true; --Str; break; 
+      case '*':
+        Type = Context.getPointerType(Type);
+        break;
+      case 'C':
+        Type = Type.getQualifiedType(QualType::Const);
+        break;
+    }
   }
+  
+  return Type;
 }
 
 /// GetBuiltinType - Return the type for the specified builtin.

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=41136&r1=41135&r2=41136&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Fri Aug 17 00:31:46 2007
@@ -423,7 +423,7 @@
   // Extra semantic analysis beyond the C type system
   private:
   
-  void CheckFunctionCall(Expr *Fn,
+  bool CheckFunctionCall(Expr *Fn,
                          SourceLocation LParenLoc, SourceLocation RParenLoc,
                          FunctionDecl *FDecl,
                          Expr** Args, unsigned NumArgsInCall);
@@ -433,6 +433,8 @@
                             bool HasVAListArg, FunctionDecl *FDecl,
                             unsigned format_idx, Expr** Args,
                             unsigned NumArgsInCall);
+  
+  bool CheckBuiltinCFStringArgument(Expr* Arg);
 };
 
 

Modified: cfe/trunk/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaChecking.cpp?rev=41136&r1=41135&r2=41136&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/Sema/SemaChecking.cpp Fri Aug 17 00:31:46 2007
@@ -28,7 +28,7 @@
 
 /// CheckFunctionCall - Check a direct function call for various correctness
 /// and safety properties not strictly enforced by the C type system.
-void
+bool
 Sema::CheckFunctionCall(Expr *Fn,
                         SourceLocation LParenLoc, SourceLocation RParenLoc,
                         FunctionDecl *FDecl,
@@ -37,10 +37,17 @@
   // Get the IdentifierInfo* for the called function.
   IdentifierInfo *FnInfo = FDecl->getIdentifier();
   
+  if (FnInfo->getBuiltinID() == 
+      Builtin::BI__builtin___CFStringMakeConstantString) {
+    assert(NumArgsInCall == 1 &&
+           "Wrong number of arguments to builtin CFStringMakeConstantString");    
+    return CheckBuiltinCFStringArgument(Args[0]);
+  }
+  
   // Search the KnownFunctionIDs for the identifier.
   unsigned i = 0, e = id_num_known_functions;
   for (; i != e; ++i) { if (KnownFunctionIDs[i] == FnInfo) break; }
-  if (i == e) return;
+  if (i == e) return true;
   
   // Printf checking.
   if (i <= id_vprintf) {
@@ -66,6 +73,46 @@
     CheckPrintfArguments(Fn, LParenLoc, RParenLoc, HasVAListArg,
 			 FDecl, format_idx, Args, NumArgsInCall);
   }
+  
+  return true;
+}
+
+/// CheckBuiltinCFStringArgument - Checks that the argument to the builtin
+/// CFString constructor is correct
+bool Sema::CheckBuiltinCFStringArgument(Expr* Arg)
+{
+  while (ParenExpr *PE = dyn_cast<ParenExpr>(Arg))
+    Arg = PE->getSubExpr();
+  
+  StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);
+
+  if (!Literal || Literal->isWide()) {
+    Diag(Arg->getLocStart(),
+         diag::err_cfstring_literal_not_string_constant,
+         Arg->getSourceRange());
+    return false;
+  }
+  
+  const char *Data = Literal->getStrData();
+  unsigned Length = Literal->getByteLength();
+  
+  for (unsigned i = 0; i < Length; ++i) {
+    if (!isascii(Data[i])) {
+      Diag(PP.AdvanceToTokenCharacter(Arg->getLocStart(), i + 1),
+           diag::warn_cfstring_literal_contains_non_ascii_character,
+           Arg->getSourceRange());
+      break;
+    }
+    
+    if (!Data[i]) {
+      Diag(PP.AdvanceToTokenCharacter(Arg->getLocStart(), i + 1),
+           diag::warn_cfstring_literal_contains_nul_character,
+           Arg->getSourceRange());
+      break;
+    }
+  }
+  
+  return true;
 }
 
 /// CheckPrintfArguments - Check calls to printf (and similar functions) for

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

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Fri Aug 17 00:31:46 2007
@@ -561,7 +561,8 @@
   if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
     if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()))
       if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()))
-        CheckFunctionCall(Fn, LParenLoc, RParenLoc, FDecl, Args, NumArgsInCall);
+        if (!CheckFunctionCall(Fn, LParenLoc, RParenLoc, FDecl, Args, NumArgsInCall))
+          return true;
 
   return new CallExpr(Fn, Args, NumArgsInCall, resultType, RParenLoc);
 }

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

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Aug 17 00:31:46 2007
@@ -36,8 +36,10 @@
   llvm::FoldingSet<FunctionTypeNoProto> FunctionTypeNoProtos;
   llvm::FoldingSet<FunctionTypeProto> FunctionTypeProtos;
   llvm::DenseMap<const RecordDecl*, const RecordLayout*> RecordLayoutInfo;
+  RecordDecl *CFConstantStringTypeDecl;
 public:
   TargetInfo &Target;
+  IdentifierTable &Idents;
   Builtin::Context BuiltinInfo;
 
   // Builtin Types.
@@ -50,7 +52,8 @@
   QualType FloatTy, DoubleTy, LongDoubleTy;
   QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
   
-  ASTContext(TargetInfo &t, IdentifierTable &idents) : Target(t) {
+  ASTContext(TargetInfo &t, IdentifierTable &idents) : 
+    CFConstantStringTypeDecl(0), Target(t), Idents(idents) {
     InitBuiltinTypes();
     BuiltinInfo.InitializeBuiltins(idents, Target);
   }    
@@ -116,6 +119,9 @@
   /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
   QualType getPointerDiffType() const;
   
+  // getCFConstantStringType - Return the type used for constant CFStrings. 
+  QualType getCFConstantStringType(); 
+  
   //===--------------------------------------------------------------------===//
   //                         Type Sizing and Analysis
   //===--------------------------------------------------------------------===//

Modified: cfe/trunk/include/clang/AST/Builtins.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Builtins.def?rev=41136&r1=41135&r2=41136&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Builtins.def (original)
+++ cfe/trunk/include/clang/AST/Builtins.def Fri Aug 17 00:31:46 2007
@@ -29,6 +29,7 @@
 //  i -> int
 //  f -> float
 //  d -> double
+//  F -> constant CFString
 //  . -> "...".  This may only occur at the end of the function list.
 //
 // Types maybe prefixed with the following modifiers:
@@ -36,6 +37,10 @@
 //  LL -> long long
 //  S  -> signed
 //  U  -> unsigned
+//
+// Types may be postfixed with the following modifiers:
+// * -> pointer
+// C -> const
 
 // The third value provided to the macro specifies information about attributes
 // of the function.  Currently we have:
@@ -50,5 +55,6 @@
 BUILTIN(__builtin_fabsl, "LdLd", "nc")
 BUILTIN(__builtin_constant_p, "UsUs", "nc")
 BUILTIN(__builtin_classify_type, "i.", "nc")
+BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
 
 #undef BUILTIN

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Fri Aug 17 00:31:46 2007
@@ -681,6 +681,14 @@
 DIAG(warn_printf_format_string_contains_null_char, WARNING,
   "format string contains '\\0' within the string body")
    
+// CFString checking
+DIAG(err_cfstring_literal_not_string_constant, ERROR,
+  "CFString literal is not a string constant")
+DIAG(warn_cfstring_literal_contains_non_ascii_character, WARNING,
+  "CFString literal contains non-ASCII character")
+DIAG(warn_cfstring_literal_contains_nul_character, WARNING,
+  "CFString literal contains NUL character")
+
 // Statements.
 DIAG(err_continue_not_in_loop, ERROR,
      "'continue' statement not in loop statement")

Added: cfe/trunk/test/Sema/cfstring.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/cfstring.c?rev=41136&view=auto

==============================================================================
--- cfe/trunk/test/Sema/cfstring.c (added)
+++ cfe/trunk/test/Sema/cfstring.c Fri Aug 17 00:31:46 2007
@@ -0,0 +1,10 @@
+#define CFSTR __builtin___CFStringMakeConstantString
+
+// RUN: clang %s -parse-ast-check
+void f() {
+  CFSTR("\242"); // expected-warning { CFString literal contains non-ASCII character }
+  CFSTR("\0"); // expected-warning { CFString literal contains NUL character }
+  CFSTR(242); // expected-error { error: CFString literal is not a string constant } \
+  expected-warning { incompatible types }
+  CFSTR("foo", "bar"); // expected-error { error: too many arguments to function }
+}





More information about the cfe-commits mailing list