Skip to content

Commit d9f786f

Browse files
authored
Reland "[Modules] Fix using va_list with modules and a precompiled header. (#100837)"
Fix the false warning > incompatible pointer types passing 'va_list' (aka '__builtin_va_list') to parameter of type 'struct __va_list_tag *' [-Wincompatible-pointer-types] The warning is wrong because both in the function declaration and at the call site we are using `va_list`. When we call `ASTContext::getBuiltinVaListDecl` at a specific moment, we end up re-entering this function which causes creating 2 instances of `BuiltinVaListDecl` and 2 instances of `VaListTagDecl` but the stored instances are unrelated to each other because of the call sequence like getBuiltinVaListDecl CreateX86_64ABIBuiltinVaListDecl VaListTagDecl = TagA indirectly call getBuiltinVaListDecl CreateX86_64ABIBuiltinVaListDecl VaListTagDecl = TagB BuiltinVaListDecl = ListB BuiltinVaListDecl = ListA Now we have `BuiltinVaListDecl == ListA` and `VaListTagDecl == TagB`. For x86_64 '__builtin_va_list' and 'struct __va_list_tag *' are compatible because '__builtin_va_list' == '__va_list_tag[1]'. But because we have unrelated decls for VaListDecl and VaListTagDecl the types are considered incompatible as we are comparing type pointers. Fix the error by creating `BuiltinVaListDecl` before `ASTReader::InitializeSema`, so that during `ASTContext::getBuiltinVaListDecl` ASTReader doesn't try to de-serialize '__builtin_va_list' and to call `ASTContext::getBuiltinVaListDecl` again. Reland with the requirement to have x86 target to avoid errors like > error: unable to create target: 'No available targets are compatible with triple "x86_64-apple-darwin"' rdar://130947515
1 parent 8cf8565 commit d9f786f

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

clang/lib/Sema/Sema.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,13 @@ void Sema::addImplicitTypedef(StringRef Name, QualType T) {
310310
}
311311

312312
void Sema::Initialize() {
313+
// Create BuiltinVaListDecl *before* ExternalSemaSource::InitializeSema(this)
314+
// because during initialization ASTReader can emit globals that require
315+
// name mangling. And the name mangling uses BuiltinVaListDecl.
316+
if (Context.getTargetInfo().hasBuiltinMSVaList())
317+
(void)Context.getBuiltinMSVaListDecl();
318+
(void)Context.getBuiltinVaListDecl();
319+
313320
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
314321
SC->InitializeSema(*this);
315322

clang/test/Modules/builtin-vararg.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Check how builtins using varargs behave with the modules.
2+
3+
// REQUIRES: x86-registered-target
4+
// RUN: rm -rf %t
5+
// RUN: split-file %s %t
6+
7+
// RUN: %clang_cc1 -triple x86_64-apple-darwin \
8+
// RUN: -fmodules -fno-implicit-modules -fbuiltin-headers-in-system-modules \
9+
// RUN: -emit-module -fmodule-name=DeclareVarargs \
10+
// RUN: -x c %t/include/module.modulemap -o %t/DeclareVarargs.pcm \
11+
// RUN: -fmodule-map-file=%t/resource_dir/module.modulemap -isystem %t/resource_dir
12+
// RUN: %clang_cc1 -triple x86_64-apple-darwin \
13+
// RUN: -fmodules -fno-implicit-modules -fbuiltin-headers-in-system-modules \
14+
// RUN: -emit-pch -fmodule-name=Prefix \
15+
// RUN: -x c-header %t/prefix.pch -o %t/prefix.pch.gch \
16+
// RUN: -fmodule-map-file=%t/include/module.modulemap -fmodule-file=DeclareVarargs=%t/DeclareVarargs.pcm \
17+
// RUN: -I %t/include
18+
// RUN: %clang_cc1 -triple x86_64-apple-darwin \
19+
// RUN: -fmodules -fno-implicit-modules -fbuiltin-headers-in-system-modules \
20+
// RUN: -emit-obj -fmodule-name=test \
21+
// RUN: -x c %t/test.c -o %t/test.o \
22+
// RUN: -Werror=incompatible-pointer-types \
23+
// RUN: -fmodule-file=%t/DeclareVarargs.pcm -include-pch %t/prefix.pch.gch \
24+
// RUN: -I %t/include
25+
26+
//--- include/declare-varargs.h
27+
#ifndef DECLARE_VARARGS_H
28+
#define DECLARE_VARARGS_H
29+
30+
#include <stdarg.h>
31+
32+
int vprintf(const char *format, va_list args);
33+
34+
// 1. initializeBuiltins 'acos' causes its deserialization and deserialization
35+
// of 'implementation_of_builtin'. Because this is done before Sema initialization,
36+
// 'implementation_of_builtin' DeclID is added to PreloadedDeclIDs.
37+
#undef acos
38+
#define acos(__x) implementation_of_builtin(__x)
39+
40+
// 2. Because of 'static' the function isn't added to EagerlyDeserializedDecls
41+
// and not deserialized in `ASTReader::StartTranslationUnit` before `ASTReader::InitializeSema`.
42+
// 3. Because of '__overloadable__' attribute the function requires name mangling during deserialization.
43+
// And the name mangling requires '__builtin_va_list' decl.
44+
// Because the function is added to PreloadedDeclIDs, the deserialization happens in `ASTReader::InitializeSema`.
45+
static int __attribute__((__overloadable__)) implementation_of_builtin(int x) {
46+
return x;
47+
}
48+
49+
#endif // DECLARE_VARARGS_H
50+
51+
//--- include/module.modulemap
52+
module DeclareVarargs {
53+
header "declare-varargs.h"
54+
export *
55+
}
56+
57+
//--- resource_dir/stdarg.h
58+
#ifndef STDARG_H
59+
#define STDARG_H
60+
61+
typedef __builtin_va_list va_list;
62+
#define va_start(ap, param) __builtin_va_start(ap, param)
63+
#define va_end(ap) __builtin_va_end(ap)
64+
65+
#endif // STDARG_H
66+
67+
//--- resource_dir/module.modulemap
68+
module _Builtin_stdarg {
69+
header "stdarg.h"
70+
export *
71+
}
72+
73+
//--- prefix.pch
74+
#include <declare-varargs.h>
75+
76+
//--- test.c
77+
#include <declare-varargs.h>
78+
79+
void test(const char *format, ...) {
80+
va_list argParams;
81+
va_start(argParams, format);
82+
vprintf(format, argParams);
83+
va_end(argParams);
84+
}

0 commit comments

Comments
 (0)