[PATCH] Implement the __builtin_call_with_static_chain GNU extension.

Peter Collingbourne peter at pcc.me.uk
Thu Dec 11 01:26:16 PST 2014


================
Comment at: include/clang/Basic/Builtins.def:500
@@ -499,2 +499,3 @@
 BUILTIN(__builtin_alloca, "v*z"   , "n")
+BUILTIN(__builtin_call_with_static_chain, "v.", "t")
 
----------------
rsmith wrote:
> This should presumably also be marked "n"; it itself never throws (its argument might, but that's a separate issue).
Done.

================
Comment at: lib/Sema/SemaChecking.cpp:177-184
@@ +176,10 @@
+
+  ExprResult ChainResult = S.UsualUnaryConversions(Chain);
+  if (ChainResult.isInvalid())
+    return true;
+  if (!ChainResult.get()->getType()->isPointerType()) {
+    S.Diag(BuiltinLoc, diag::err_second_argument_to_cwsc_not_pointer)
+        << Chain->getSourceRange();
+    return true;
+  }
+
----------------
rsmith wrote:
> It might be better to perform conversions as if to a parameter of type `void *` here (that would be detectable in C++ via conversion operators, and would do the right thing for null pointer constants). What does GCC do in those cases?
GCC appears to only support the extension in C mode, not in C++. It appears to check the second argument's type rather than attempting any implicit conversions, so null pointer constants are rejected. I couldn't identify any cases (in C) where we reject a second argument that GCC accepts or vice versa.

================
Comment at: lib/Sema/SemaChecking.cpp:187
@@ +186,3 @@
+  BuiltinCall->setType(CE->getType());
+  BuiltinCall->getCallee()->setType(CE->getCallee()->getType());
+  BuiltinCall->setValueKind(CE->getValueKind());
----------------
rsmith wrote:
> This can't be right: multiple calls to the builtin will share the same callee and will want different types here. Just remove this line?
I found this to be necessary in cases where the function returns an lvalue; without it, I was getting assertion failures.

I thought this might be an issue as well, until I looked at the AST representation of builtin calls:

```
|     |-CallExpr 0x4310ae0 <col:3, col:42> 'int' lvalue
|     | |-ImplicitCastExpr 0x4310ac8 <col:3> 'int &(*)(void)' <BuiltinFnToFnPtr>
|     | | `-DeclRefExpr 0x4310960 <col:3> '<builtin fn type>' Function 0x43108c0 '__builtin_call_with_static_chain' 'void ()'
|     | |-CallExpr 0x4310a50 <col:36, col:38> 'int' lvalue
|     | | `-ImplicitCastExpr 0x4310a38 <col:36> 'int &(*)(void)' <FunctionToPointerDecay>
|     | |   `-DeclRefExpr 0x43109e0 <col:36> 'int &(void)' lvalue Function 0x42ca430 'f' 'int &(void)'
|     | `-ImplicitCastExpr 0x4310b18 <col:41> 'int &(*)(void)' <FunctionToPointerDecay>
|     |   `-DeclRefExpr 0x4310a78 <col:41> 'int &(void)' lvalue Function 0x42ca430 'f' 'int &(void)'
```

So we are only overwriting the type of the `BuiltinFnToFnPtr` cast. This seems to be not too bad (except that the argument types are wrong; I should fix that, but it didn't seem to cause any issues).

http://reviews.llvm.org/D6332

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/






More information about the cfe-commits mailing list