tbaeder created this revision. tbaeder added a reviewer: clang. Herald added a project: All. tbaeder requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
I'm not 100% sure if this is crazy or not, but it doesn't even seem to break any existing test cases. We evaluate all integer expressions for overflows and diagnose them if possible. However, in the case of a constexpr function, we will evaluate the function (and all expressions it contains) anyway after parsing it, which will check for overflow again, so the previous checking is unnecessary. I checked that not calling `CheckForIntOverflow()` at all breaks tests (it does). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D138270 Files: clang/include/clang/Sema/Sema.h clang/lib/Sema/Sema.cpp clang/lib/Sema/SemaChecking.cpp Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -15542,11 +15542,14 @@ bool IsConstexpr) { llvm::SaveAndRestore<bool> ConstantContext( isConstantEvaluatedOverride, IsConstexpr || isa<ConstantExpr>(E)); + CheckImplicitConversions(E, CheckLoc); if (!E->isInstantiationDependent()) CheckUnsequencedOperations(E); - if (!IsConstexpr && !E->isValueDependent()) + + if (!IsConstexpr && !E->isValueDependent() && !curFunctionDeclIsConstexpr()) CheckForIntOverflow(E); + DiagnoseMisalignedMembers(); } Index: clang/lib/Sema/Sema.cpp =================================================================== --- clang/lib/Sema/Sema.cpp +++ clang/lib/Sema/Sema.cpp @@ -1438,7 +1438,7 @@ // Helper functions. //===----------------------------------------------------------------------===// -DeclContext *Sema::getFunctionLevelDeclContext(bool AllowLambda) { +DeclContext *Sema::getFunctionLevelDeclContext(bool AllowLambda) const { DeclContext *DC = CurContext; while (true) { @@ -1458,7 +1458,7 @@ /// getCurFunctionDecl - If inside of a function body, this returns a pointer /// to the function decl for the function being parsed. If we're currently /// in a 'block', this returns the containing context. -FunctionDecl *Sema::getCurFunctionDecl(bool AllowLambda) { +FunctionDecl *Sema::getCurFunctionDecl(bool AllowLambda) const { DeclContext *DC = getFunctionLevelDeclContext(AllowLambda); return dyn_cast<FunctionDecl>(DC); } Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -3503,13 +3503,18 @@ void ActOnExitFunctionContext(); /// If \p AllowLambda is true, treat lambda as function. - DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false); + DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false) const; /// Returns a pointer to the innermost enclosing function, or nullptr if the /// current context is not inside a function. If \p AllowLambda is true, /// this can return the call operator of an enclosing lambda, otherwise /// lambdas are skipped when looking for an enclosing function. - FunctionDecl *getCurFunctionDecl(bool AllowLambda = false); + FunctionDecl *getCurFunctionDecl(bool AllowLambda = false) const; + + bool curFunctionDeclIsConstexpr() const { + const FunctionDecl *FD = getCurFunctionDecl(); + return FD ? FD->isConstexpr() : false; + } /// getCurMethodDecl - If inside of a method body, this returns a pointer to /// the method decl for the method being parsed. If we're currently
Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -15542,11 +15542,14 @@ bool IsConstexpr) { llvm::SaveAndRestore<bool> ConstantContext( isConstantEvaluatedOverride, IsConstexpr || isa<ConstantExpr>(E)); + CheckImplicitConversions(E, CheckLoc); if (!E->isInstantiationDependent()) CheckUnsequencedOperations(E); - if (!IsConstexpr && !E->isValueDependent()) + + if (!IsConstexpr && !E->isValueDependent() && !curFunctionDeclIsConstexpr()) CheckForIntOverflow(E); + DiagnoseMisalignedMembers(); } Index: clang/lib/Sema/Sema.cpp =================================================================== --- clang/lib/Sema/Sema.cpp +++ clang/lib/Sema/Sema.cpp @@ -1438,7 +1438,7 @@ // Helper functions. //===----------------------------------------------------------------------===// -DeclContext *Sema::getFunctionLevelDeclContext(bool AllowLambda) { +DeclContext *Sema::getFunctionLevelDeclContext(bool AllowLambda) const { DeclContext *DC = CurContext; while (true) { @@ -1458,7 +1458,7 @@ /// getCurFunctionDecl - If inside of a function body, this returns a pointer /// to the function decl for the function being parsed. If we're currently /// in a 'block', this returns the containing context. -FunctionDecl *Sema::getCurFunctionDecl(bool AllowLambda) { +FunctionDecl *Sema::getCurFunctionDecl(bool AllowLambda) const { DeclContext *DC = getFunctionLevelDeclContext(AllowLambda); return dyn_cast<FunctionDecl>(DC); } Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -3503,13 +3503,18 @@ void ActOnExitFunctionContext(); /// If \p AllowLambda is true, treat lambda as function. - DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false); + DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false) const; /// Returns a pointer to the innermost enclosing function, or nullptr if the /// current context is not inside a function. If \p AllowLambda is true, /// this can return the call operator of an enclosing lambda, otherwise /// lambdas are skipped when looking for an enclosing function. - FunctionDecl *getCurFunctionDecl(bool AllowLambda = false); + FunctionDecl *getCurFunctionDecl(bool AllowLambda = false) const; + + bool curFunctionDeclIsConstexpr() const { + const FunctionDecl *FD = getCurFunctionDecl(); + return FD ? FD->isConstexpr() : false; + } /// getCurMethodDecl - If inside of a method body, this returns a pointer to /// the method decl for the method being parsed. If we're currently
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits