<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/67156>67156</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Clang attr emitter tablegen target should guard optional arguments
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang,
tablegen,
crash-on-valid
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
steakhal
</td>
</tr>
</table>
<pre>
I noticed a crash for the following valid code when using the `-ast-print` flag:
https://godbolt.org/z/78xYbEosb
```C++
void *top() __attribute__((assume_aligned(__alignof__(unsigned long long))));
```
The AST looks like this:
```
TranslationUnitDecl
`-FunctionDecl <line:1:1, col:76> col:7 top 'void *()'
`-AssumeAlignedAttr <col:28, col:74>
|-UnaryExprOrTypeTraitExpr <col:43, col:73> 'unsigned long' __alignof 'unsigned long long'
`-<<<NULL>>>
```
Notice the last NULL node.
In the clang/include/clang/Basic/Attr.td, we can see that `AssumeAligned` is defined like this:
```
def AssumeAligned : InheritableAttr {
let Spellings = [GCC<"assume_aligned">];
let Subjects = SubjectList<[ObjCMethod, Function]>;
let Args = [ExprArgument<"Alignment">, ExprArgument<"Offset", 1>];
let Documentation = [AssumeAlignedDocs];
}
```
Notice the `ExprArgument<"Offset", 1>`, where `1` denotes that this argument is optional, thus might be null.
There are a couple other attributes where we set this flag, but they are really rare.
I found only `CUDALaunchBounds`, `AMDGPUWavesPerEU` and `AssumeAligned`.
Apparently, inside clang/utils/TableGen/ClangAttrEmitter.cpp:`ExprArgument::writeValue`, we emit code that doesn't guard optional arguments before visiting them:
```C++
void writeValue(raw_ostream &OS) const override {
OS << "\";\n";
OS << " get" << getUpperName()
<< "()->printPretty(OS, nullptr, Policy);\n";
OS << " OS << \"";
}
```
It should have guarded the call to `printPretty()` to make sure the pointer is valid.
I suspect, that other emit functions suffer from this issue.
This is present on clang-16, and on trunk as of now.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyMVl9v4jgQ_zTmZQQKTknggYcQYFWpu63U9k73VDnJJPHW2JE9aZf79Cc7gdJ293YlE-zxzHj-_GZs4ZxsNOKaLTZssZ2Inlpj145QPLdCTQpTHdfXoA3JEisQUFrhWqiNBWoRaqOUeZW6gRehZAWlqRBeW9TQO0_1PCyJpsLRtLNSE0siqJVoWJyxaMuirCXqnF_xPeP7xlSFUTQztmF8_y_j-3T5459iZ1wxsLMkGkbO-MaPQH0xsgLGMzId40vGV_D0JIisLHrCp6dAWwrn-gM-CeUdrhhfPg1zUweOXodIVKCMbsKH8dXbiDcfDBiX4fvQImT3D6CMeXag5DMCtdKdnfwg9GCFdkqQNPpRS9piqc58032vS7_jqcDiXEmNLM7m4cdzKI1icZYmLN6d5kCmA8bTUxiGGDCeDlohpCAL7meD9xmR9coHBZ79rPiKxbtRjqX59FELe9z96OytfTh2-GCFJL98k76KL6Rjbxbj6btoMp7COdifdk8sJ2MHc1mcD-Pb482NN2kYv87BtwDRgDglHIGXA20qnF1yXevAUSrhz9xLXaq-Qsb3J8pGOFkyvvcRmlHlXXtFKIUGh167IG_eu2B6TEsHFdYy-PS79FdYwzsFwOIMrnWLVpIoFA7ZSTeniCgkuO9QKakbByzeAltsvuQhQJx_xDX3cVpsz4gd5fviO5Y0iI-LG-nI61hsbovv-Vek1gSHTxAMWnYfFGX2zQYPhMw2_QE1DcYEj8JysIPn8Jnptq4dBg6ew_yn5m5NGQRCkZyOexe0rSndpRxLt3-GDpZEf2JSEoXct2iDyNxnuUJtCN0AA59iEKMWDwDTeWOF8nLU9g4OsmkJCgTdKzU7twqLIPwPStN3CsFQixbO_cqNh74iOByPCS2T51D0noDHoMCiUOoIVtgTxq-hNr2uwGh19Ebnj9vsRvS6bDee7kanPIC_br_cPf4tXtDdod09eu-Ern6G7Xf1k3WdsKhJHb0iqZ2s3qqpJ6kc4_sHD-IvqBnf537L43l3kERoZ2XX-br4mIOMxdmrlYR_CdXjKfgIeJA03Coh5pVBpxlPCZpe2Ooc8nMeHBRYG4vwIp2k8Qo6fK7Ez9fHxel8acXrk3FkURyA8eT23t8ppdGOwLygtd7riwK9vYehWYFH0CIP4N-wRa7H2c_4fKdrAuZOxAbpsevQfhMHHHv4uSdeHhC2pizehSv1ziLRkfGltzIPWOvI-umdUbI8jrfX7425IAwuXLD_f3VdE7jW9KqCVrzgkBushk4rlAIyHljvrfVmJZHfOohnBNfboTw7IzWh9QUV3hRnaLvedVjSUF2CxrIJAKnHhuXA9XWNFmprDkPlSOf691fAw0CGzqLzlWv0AODpPPG6RagfINvrZxAOTA3avM4m1TquVvFKTHA9T1aLeJVGy3jSrqOqWAoe8ZSXyTJNS6x5lcyLq7pciXlSxBO55hGPoxXn80WcLtJZsqyKeSXq6KqOVsmiZFcRHoRUM6VeDv7pMwlGr5N0vkgmShSoXHifcT5Wmu9SjPNwWTSoz4TwOJsaPQ2RC1jcTuza650WfePYVaSkI_d2EklSuA5VGjpQiKcP_0k3kLANnvP7y7Kb9FatPzzmJLV9MSvNgfG9P3H8m3bWfA-Z3AdHfcsIvv4XAAD__0UtM6w">