Skip to content

Commit 815fe26

Browse files
committed
Don't warn for -Wstatic-in-inline if the used function is also inline.
Also, don't warn if the used function is __attribute__((const)), in which case it's not supposed to use global variables anyway. The inline-in-inline thing is a heuristic, and one that's possibly incorrect fairly often because the function being inlined could definitely use global variables. However, even some C standard library functions are written using other (trivial) static-inline functions in the headers, and we definitely don't want to be warning on that (or on anything that /uses/ these trivial inline functions). So we're using "inlined" as a marker for "fairly trivial". (Note that __attribute__((pure)) does /not/ guarantee safety like ((const), because ((const)) does not guarantee that global variables are not being used, and the warning is about globals not being shared across TUs.) llvm-svn: 158898
1 parent f0dcac6 commit 815fe26

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

clang/lib/Sema/SemaExpr.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,21 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
172172
if (D->getLinkage() != InternalLinkage)
173173
return;
174174

175-
// Don't warn unless -pedantic is on if the inline function is in the main
176-
// source file. This function will most likely not be inlined into
177-
// another translation unit, so it's effectively internal.
178-
bool IsInMainFile = S.getSourceManager().isFromMainFile(Loc);
179-
S.Diag(Loc, IsInMainFile ? diag::ext_internal_in_extern_inline
180-
: diag::warn_internal_in_extern_inline)
181-
<< isa<VarDecl>(D) << D;
175+
// Downgrade from ExtWarn to Extension if
176+
// (1) the supposedly external inline function is in the main file,
177+
// and probably won't be included anywhere else.
178+
// (2) the thing we're referencing is a pure function.
179+
// (3) the thing we're referencing is another inline function.
180+
// This last can give us false negatives, but it's better than warning on
181+
// wrappers for simple C library functions.
182+
const FunctionDecl *UsedFn = dyn_cast<FunctionDecl>(D);
183+
bool DowngradeWarning = S.getSourceManager().isFromMainFile(Loc);
184+
if (!DowngradeWarning && UsedFn)
185+
DowngradeWarning = UsedFn->isInlined() || UsedFn->hasAttr<ConstAttr>();
186+
187+
S.Diag(Loc, DowngradeWarning ? diag::ext_internal_in_extern_inline
188+
: diag::warn_internal_in_extern_inline)
189+
<< /*IsVar=*/!UsedFn << D;
182190

183191
// Suggest "static" on the inline function, if possible.
184192
if (!hasAnyExplicitStorageClass(Current)) {

clang/test/Sema/inline.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ static inline int useStaticFromStatic () {
2626
return staticVar; // no-warning
2727
}
2828

29+
extern inline int useStaticInlineFromExtern () {
30+
// Heuristic: if the function we're using is also inline, don't warn.
31+
// This can still be wrong (in this case, we end up inlining calls to
32+
// staticFunction and staticVar) but this got very noisy even using
33+
// standard headers.
34+
return useStaticFromStatic(); // no-warning
35+
}
36+
37+
static int constFunction() __attribute__((const));
38+
39+
inline int useConst () {
40+
return constFunction(); // no-warning
41+
}
42+
2943
#else
3044
// -------
3145
// This is the main source file.

0 commit comments

Comments
 (0)