aaron.ballman marked 3 inline comments as done. aaron.ballman added a subscriber: NoQ. aaron.ballman added inline comments.
================ Comment at: clang/include/clang/Basic/LangOptions.def:124 BENIGN_LANGOPT(ImplicitInt, 1, 0, "C89 implicit 'int'") +LANGOPT(StrictPrototypes , 1, 0, "require function types to have a prototype") LANGOPT(Digraphs , 1, 0, "digraphs") ---------------- rsmith wrote: > This makes me think we should have some declarative way of specifying > dependencies between `LANGOPT`s. It's presumably sufficiently obvious to a > library user that they shouldn't enable (eg) `CPlusPlus20` unless they enable > all the previous `CPlusPlusXY` modes and `CPlusPlus`, but I doubt it's > obvious that enabling `CPlusPlus` requires also enabling `StrictPrototypes`. > > In fact, after this change, I think a lot of existing library users of Clang > that invent their own `LangOptions` will silently start getting this wrong. > That's concerning. Maybe we should consider prototypes to be required if > either `StrictPrototypes` or `CPlusPlus` is enabled? > This makes me think we should have some declarative way of specifying > dependencies between LANGOPTs. Tee hee: https://github.com/llvm/llvm-project/commit/be9371659380388a693ec99624e1f3d02f07047f I was caught by the same issues that I ended up fixing in that commit -- I tried making `StrictPrototypes` dependent and was very surprised when it doesn't work. The issue was `Invocation->getLangOpts()->resetNonModularOptions();` in `compileModuleImpl()` IIRC -- it would clear all of the language options (including ones like digraphs and wchar support). > In fact, after this change, I think a lot of existing library users of Clang > that invent their own LangOptions will silently start getting this wrong. > That's concerning. Maybe we should consider prototypes to be required if > either StrictPrototypes or CPlusPlus is enabled? @cor3ntin also shared this same concern -- my goal with this language option was: * Make it easy to reenable functions without prototypes in C2x mode if we find some major breakage in the wild (hopefully we don't) * Make it easy to add `-fstrict-prototypes` as a language flag to opt *into* strict prototypes (there would be no option to opt *out* of strict prototypes). * Stop repeating `CPlusPlus || C2x` in a bunch of places and give it a named option. So I'm not keen on adding `StrictPrototypes || CPlusPlus` everywhere -- C++ requires strict prototypes. However, the fears are still valid -- what if I found someplace nice to add an assert that `StrictPrototypes` cannot be false when `CPlusPlus` is true? ================ Comment at: clang/lib/Parse/ParseDecl.cpp:6664-6666 + // OpenCL disallows variadic functions, so it also disallows a function + // without a prototype. However, it doesn't enforce strict prototypes + // because it allows function definitions with an identifier list. ---------------- rsmith wrote: > I don't follow this comment: functions without a prototype are not variadic > (they're compatible with any *non-variadic* prototype), so OpenCL disallowing > variadic functions seems irrelevant here. Heh, this comment came from feedback I got from someone on IRC when I was asking what OpenCL actually supports. As best I found, OpenCL allows `void f();` to mean `void f(void);` as in C++, but also allows `void f(a, b) int a, b; {}` (despite having no way to actually declare this function). I'll take a pass at fixing up the comment to be more clear, thanks! ================ Comment at: clang/lib/Sema/SemaType.cpp:5273-5275 + // OpenCL disallows variadic functions, so it also disallows a function + // without a prototype. However, it doesn't enforce strict prototypes + // because it allows function definitions with an identifier list. ---------------- rsmith wrote: > Same as before, OpenCL disallowing variadics doesn't seem relevant here. Same here as above. ================ Comment at: clang/lib/StaticAnalyzer/Core/MemRegion.cpp:1034-1042 + if (T.isNull() || !T->getAs<FunctionType>()) + // If the type is invalid or is not a function type, we cannot get + // a block pointer type for it. This isn't ideal, but it's better + // than asserting in getBlockPointerType() or creating a function + // without a prototype in a language that has no such concept (like + // C++ or C2x). + sReg = getUnknownRegion(); ---------------- rsmith wrote: > I find it really surprising that the "signature is present but is not a > function type" case is reachable -- the static analyzer should only run on > valid code, and in valid code I'd expect the signature of a block would > always be a function type. Is that case actually reached in our test suite? > > I worry that the "block has no explicit signature" case here is common, and > that we're losing substantial coverage in that case. Per > https://clang.llvm.org/docs/BlockLanguageSpec.html#block-literal-expressions, > `^ { ... }` is equivalent to `^ (void) { ... }`, so it seems the original > code here was just wrong and we should always have been creating a > `FunctionProtoType` in this case. I tried raising someone from the static analyzer team on IRC and failed, so this was my best guess. Without this change, we get two assertions (when I enabled the asserts in `getFunctionNoProtoType()`): test/Analysis/blocks.m and test/Analysis/templates.cpp. So we definitely reach this spot. Given the FIXME comment above my changes, it looks like the analyzer folks knew they were doing something wrong here. With these changes, I get no test failures, so I'm not certain we're losing substantial coverage or not. I think you might be correct about creating a function with a prototype. @NoQ -- do you agree with that fix? CHANGES SINCE LAST ACTION https://reviews.llvm.org/D123955/new/ https://reviews.llvm.org/D123955 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits