[cfe-commits] r126539 - in /cfe/trunk: include/clang/Basic/Builtins.def include/clang/Basic/Builtins.h lib/Sema/SemaChecking.cpp lib/Sema/SemaExpr.cpp

John McCall rjmccall at apple.com
Fri Feb 25 21:39:39 PST 2011


Author: rjmccall
Date: Fri Feb 25 23:39:39 2011
New Revision: 126539

URL: http://llvm.org/viewvc/llvm-project?rev=126539&view=rev
Log:
Provide a bit saying that a builtin undergoes custom type-checking, then
don't let calls to such functions go down the normal type-checking path.
Test this out with __builtin_classify_type and __builtin_constant_p.


Modified:
    cfe/trunk/include/clang/Basic/Builtins.def
    cfe/trunk/include/clang/Basic/Builtins.h
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/include/clang/Basic/Builtins.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=126539&r1=126538&r2=126539&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Builtins.def (original)
+++ cfe/trunk/include/clang/Basic/Builtins.def Fri Feb 25 23:39:39 2011
@@ -60,6 +60,7 @@
 //  n -> nothrow
 //  r -> noreturn
 //  c -> const
+//  t -> signature is meaningless, use custom typechecking
 //  F -> this is a libc/libm function with a '__builtin_' prefix added.
 //  f -> this is a libc/libm function without the '__builtin_' prefix. It can
 //       be followed by ':headername:' to state which header this function
@@ -383,8 +384,8 @@
 BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
 
 // Random GCC builtins
-BUILTIN(__builtin_constant_p, "i.", "nc")
-BUILTIN(__builtin_classify_type, "i.", "nc")
+BUILTIN(__builtin_constant_p, "i.", "nct")
+BUILTIN(__builtin_classify_type, "i.", "nct")
 BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
 BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
 BUILTIN(__builtin_va_start, "vA.", "n")

Modified: cfe/trunk/include/clang/Basic/Builtins.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.h?rev=126539&r1=126538&r2=126539&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Builtins.h (original)
+++ cfe/trunk/include/clang/Basic/Builtins.h Fri Feb 25 23:39:39 2011
@@ -117,6 +117,11 @@
     return strchr(GetRecord(ID).Attributes, 'f') != 0;
   }
 
+  /// \brief Determines whether this builtin has custom typechecking.
+  bool hasCustomTypechecking(unsigned ID) const {
+    return strchr(GetRecord(ID).Attributes, 't') != 0;
+  }
+
   /// \brief Completely forget that the given ID was ever considered a builtin,
   /// e.g., because the user provided a conflicting signature.
   void ForgetBuiltin(unsigned ID, IdentifierTable &Table);

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=126539&r1=126538&r2=126539&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Feb 25 23:39:39 2011
@@ -66,6 +66,26 @@
   return false;
 }
 
+/// Checks that a call expression's argument count is the desired number.
+/// This is useful when doing custom type-checking.  Returns true on error.
+static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) {
+  unsigned argCount = call->getNumArgs();
+  if (argCount == desiredArgCount) return false;
+
+  if (argCount < desiredArgCount)
+    return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args)
+        << 0 /*function call*/ << desiredArgCount << argCount
+        << call->getSourceRange();
+
+  // Highlight all the excess arguments.
+  SourceRange range(call->getArg(desiredArgCount)->getLocStart(),
+                    call->getArg(argCount - 1)->getLocEnd());
+    
+  return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args)
+    << 0 /*function call*/ << desiredArgCount << argCount
+    << call->getArg(1)->getSourceRange();
+}
+
 ExprResult
 Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
   ExprResult TheCallResult(Owned(TheCall));
@@ -137,15 +157,14 @@
     if (SemaBuiltinLongjmp(TheCall))
       return ExprError();
     break;
+
+  case Builtin::BI__builtin_classify_type:
+    if (checkArgCount(*this, TheCall, 1)) return true;
+    TheCall->setType(Context.IntTy);
+    break;
   case Builtin::BI__builtin_constant_p:
-    if (TheCall->getNumArgs() == 0)
-      return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
-        << 0 /*function call*/ << 1 << 0 << TheCall->getSourceRange();
-    if (TheCall->getNumArgs() > 1)
-      return Diag(TheCall->getArg(1)->getLocStart(),
-                  diag::err_typecheck_call_too_many_args)
-        << 0 /*function call*/ << 1 << TheCall->getNumArgs()
-        << TheCall->getArg(1)->getSourceRange();
+    if (checkArgCount(*this, TheCall, 1)) return true;
+    TheCall->setType(Context.IntTy);
     break;
   case Builtin::BI__sync_fetch_and_add:
   case Builtin::BI__sync_fetch_and_sub:

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=126539&r1=126538&r2=126539&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Feb 25 23:39:39 2011
@@ -4281,6 +4281,13 @@
                               const FunctionProtoType *Proto,
                               Expr **Args, unsigned NumArgs,
                               SourceLocation RParenLoc) {
+  // Bail out early if calling a builtin with custom typechecking.
+  // We don't need to do this in the 
+  if (FDecl)
+    if (unsigned ID = FDecl->getBuiltinID())
+      if (Context.BuiltinInfo.hasCustomTypechecking(ID))
+        return false;
+
   // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
   // assignment, to the types of the corresponding parameter, ...
   unsigned NumArgsInProto = Proto->getNumArgs();
@@ -4608,22 +4615,27 @@
                                      RParenLoc);
   }
 
+  unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);
+
+  // Bail out early if calling a builtin with custom typechecking.
+  if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
+    return CheckBuiltinFunctionCall(BuiltinID, TheCall);
+
   const FunctionType *FuncT;
-  if (!Fn->getType()->isBlockPointerType()) {
+  if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
     // C99 6.5.2.2p1 - "The expression that denotes the called function shall
     // have type pointer to function".
-    const PointerType *PT = Fn->getType()->getAs<PointerType>();
-    if (PT == 0)
-      return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
-        << Fn->getType() << Fn->getSourceRange());
     FuncT = PT->getPointeeType()->getAs<FunctionType>();
-  } else { // This is a block call.
-    FuncT = Fn->getType()->getAs<BlockPointerType>()->getPointeeType()->
-                getAs<FunctionType>();
-  }
-  if (FuncT == 0)
+    if (FuncT == 0)
+      return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+                         << Fn->getType() << Fn->getSourceRange());
+  } else if (const BlockPointerType *BPT =
+               Fn->getType()->getAs<BlockPointerType>()) {
+    FuncT = BPT->getPointeeType()->castAs<FunctionType>();
+  } else {
     return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
       << Fn->getType() << Fn->getSourceRange());
+  }
 
   if (getLangOptions().CUDA) {
     if (Config) {
@@ -4718,7 +4730,7 @@
     if (CheckFunctionCall(FDecl, TheCall))
       return ExprError();
 
-    if (unsigned BuiltinID = FDecl->getBuiltinID())
+    if (BuiltinID)
       return CheckBuiltinFunctionCall(BuiltinID, TheCall);
   } else if (NDecl) {
     if (CheckBlockCall(NDecl, TheCall))





More information about the cfe-commits mailing list