diff options
-rw-r--r-- | basic/source/comp/codegen.cxx | 4 | ||||
-rw-r--r-- | compilerplugins/clang/loopvartoosmall.cxx | 11 | ||||
-rw-r--r-- | compilerplugins/clang/oncevar.cxx | 63 | ||||
-rw-r--r-- | compilerplugins/clang/test/oncevar.cxx | 5 |
4 files changed, 65 insertions, 18 deletions
diff --git a/basic/source/comp/codegen.cxx b/basic/source/comp/codegen.cxx index 384344e2f9b1..64791af66671 100644 --- a/basic/source/comp/codegen.cxx +++ b/basic/source/comp/codegen.cxx @@ -22,6 +22,7 @@ #include "image.hxx" #include "codegen.hxx" #include "parser.hxx" +#include <cstddef> #include <limits> #include <algorithm> #include <osl/diagnose.h> @@ -408,9 +409,8 @@ private: const sal_uInt8* m_pCode; static T readParam( sal_uInt8 const *& pCode ) { - short nBytes = sizeof( T ); T nOp1=0; - for ( int i=0; i<nBytes; ++i ) + for ( std::size_t i=0; i<sizeof( T ); ++i ) nOp1 |= *pCode++ << ( i * 8); return nOp1; } diff --git a/compilerplugins/clang/loopvartoosmall.cxx b/compilerplugins/clang/loopvartoosmall.cxx index f9c25eb4d8a9..66eda67167e2 100644 --- a/compilerplugins/clang/loopvartoosmall.cxx +++ b/compilerplugins/clang/loopvartoosmall.cxx @@ -149,7 +149,16 @@ void LoopVarTooSmall::checkSubExpr(Expr const * expr, bool positive) { return; unsigned qt2BitWidth; llvm::APSInt aIntResult; - if (binOpRHS->EvaluateAsInt(aIntResult, compiler.getASTContext())) { + // Work around missing Clang 3.9 fix <https://reviews.llvm.org/rL271762> + // "Sema: do not attempt to sizeof a dependent type", causing Clang 3.8 to + // crash during EvaluateAsInt() on expressions of the form + // + // sizeof (T) + // + // with dependent type T: + if (!binOpRHS->isValueDependent() + && binOpRHS->EvaluateAsInt(aIntResult, compiler.getASTContext())) + { if (less && aIntResult.isStrictlyPositive()) { --aIntResult; } diff --git a/compilerplugins/clang/oncevar.cxx b/compilerplugins/clang/oncevar.cxx index e7b55a09421f..7fae0e17f776 100644 --- a/compilerplugins/clang/oncevar.cxx +++ b/compilerplugins/clang/oncevar.cxx @@ -7,6 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <cassert> #include <string> #include <iostream> #include <unordered_map> @@ -15,6 +16,7 @@ #include "plugin.hxx" #include "check.hxx" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" // Original idea from tml. // Look for variables that are (a) initialised from zero or one constants. (b) only used in one spot. @@ -27,6 +29,43 @@ bool startsWith(const std::string& rStr, const char* pSubStr) { return rStr.compare(0, strlen(pSubStr), pSubStr) == 0; } +class ConstantValueDependentExpressionVisitor: + public ConstStmtVisitor<ConstantValueDependentExpressionVisitor, bool> +{ + ASTContext const & context_; + +public: + ConstantValueDependentExpressionVisitor(ASTContext const & context): + context_(context) {} + + bool Visit(Stmt const * stmt) { + assert(isa<Expr>(stmt)); + auto const expr = cast<Expr>(stmt); + if (!expr->isValueDependent()) { + return expr->isEvaluatable(context_); + } + return ConstStmtVisitor::Visit(stmt); + } + + bool VisitParenExpr(ParenExpr const * expr) + { return Visit(expr->getSubExpr()); } + + bool VisitCastExpr(CastExpr const * expr) { + return Visit(expr->getSubExpr()); + } + + bool VisitUnaryOperator(UnaryOperator const * expr) + { return Visit(expr->getSubExpr()); } + + bool VisitBinaryOperator(BinaryOperator const * expr) { + return Visit(expr->getLHS()) && Visit(expr->getRHS()); + } + + bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr const *) { + return true; + } +}; + class OnceVar: public RecursiveASTVisitor<OnceVar>, public loplugin::Plugin { @@ -99,6 +138,11 @@ private: std::unordered_set<VarDecl const *> maVarDeclToIgnoreSet; std::unordered_map<VarDecl const *, int> maVarUsesMap; std::unordered_map<VarDecl const *, SourceRange> maVarUseSourceRangeMap; + + bool isConstantValueDependentExpression(Expr const * expr) { + return ConstantValueDependentExpressionVisitor(compiler.getASTContext()) + .Visit(expr); + } }; bool OnceVar::VisitVarDecl( const VarDecl* varDecl ) @@ -164,21 +208,10 @@ bool OnceVar::VisitVarDecl( const VarDecl* varDecl ) } if (!foundStringLiteral) { auto const init = varDecl->getInit(); -#if CLANG_VERSION < 30900 - // Work around missing Clang 3.9 fix <https://reviews.llvm.org/rL271762> - // "Sema: do not attempt to sizeof a dependent type" (while an - // initializer expression of the form - // - // sizeof (T) - // - // with dependent type T /is/ constant, keep consistent here with the - // (arguably broken) behavior of isConstantInitializer returning false - // in Clang >= 3.9): - if (init->isValueDependent()) { - return true; - } -#endif - if (!init->isConstantInitializer(compiler.getASTContext(), false/*ForRef*/)) + if (!(init->isValueDependent() + ? isConstantValueDependentExpression(init) + : init->isConstantInitializer( + compiler.getASTContext(), false/*ForRef*/))) { return true; } diff --git a/compilerplugins/clang/test/oncevar.cxx b/compilerplugins/clang/test/oncevar.cxx index 32ff42d4479d..8c7b8d2a9e1d 100644 --- a/compilerplugins/clang/test/oncevar.cxx +++ b/compilerplugins/clang/test/oncevar.cxx @@ -18,6 +18,11 @@ void call_value(OUString); void call_const_ref(OUString const &); void call_ref(OUString &); +template<typename T> void f() { + int i = sizeof (T) + 1; // expected-error {{var used only once, should be inlined or declared const [loplugin:oncevar]}} + call_value(i); // expected-note {{used here [loplugin:oncevar]}} +} + int main() { /* TODO int i; |