File indexing completed on 2024-04-28 16:57:48

0001 /*
0002   This file is part of the clazy static checker.
0003 
0004     Copyright (C) 2016 Sergio Martins <smartins@kde.org>
0005     Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
0006 
0007     This library is free software; you can redistribute it and/or
0008     modify it under the terms of the GNU Library General Public
0009     License as published by the Free Software Foundation; either
0010     version 2 of the License, or (at your option) any later version.
0011 
0012     This library is distributed in the hope that it will be useful,
0013     but WITHOUT ANY WARRANTY; without even the implied warranty of
0014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015     Library General Public License for more details.
0016 
0017     You should have received a copy of the GNU Library General Public License
0018     along with this library; see the file COPYING.LIB.  If not, write to
0019     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020     Boston, MA 02110-1301, USA.
0021 */
0022 
0023 #ifndef CLAZY_ACCESS_SPECIFIER_MANAGER_H
0024 #define CLAZY_ACCESS_SPECIFIER_MANAGER_H
0025 
0026 #include "checkbase.h"
0027 
0028 #include <clang/Frontend/CompilerInstance.h>
0029 #include <clang/Basic/SourceLocation.h>
0030 #include <clang/Basic/Specifiers.h>
0031 #include <llvm/ADT/StringRef.h>
0032 
0033 #include <unordered_map>
0034 #include <vector>
0035 
0036 /*
0037    clang supports "public", "private" and "protected"
0038    This is a small wrapper to have support for "public slots", "signals", etc. so you can easily
0039    query if a method is a signal or slot
0040 
0041    This works in two steps, first the pre-processor kicks in and we use a PPCallbacks class to catch
0042    Q_SLOTS and Q_SIGNALS, then the normal access specifiers come in from the AST, inside VisitDeclaration().
0043 
0044    After that we just need to merge the two lists, and sort by source location. All the info is kept
0045    inside m_specifiersMap, which is indexed by the class definition.
0046 */
0047 
0048 namespace clang
0049 {
0050 class SourceManager;
0051 class LangOptions;
0052 class Decl;
0053 class CXXRecordDecl;
0054 class SourceLocation;
0055 class CXXMethodDecl;
0056 class CompilerInstance;
0057 }
0058 
0059 class AccessSpecifierPreprocessorCallbacks;
0060 class ClazyContext;
0061 
0062 enum QtAccessSpecifierType
0063 {
0064     QtAccessSpecifier_None,
0065     QtAccessSpecifier_Unknown,
0066     QtAccessSpecifier_Slot,
0067     QtAccessSpecifier_Signal,
0068     QtAccessSpecifier_Invokable
0069 };
0070 
0071 struct ClazyAccessSpecifier
0072 {
0073     clang::SourceLocation loc;
0074     clang::AccessSpecifier accessSpecifier;
0075     QtAccessSpecifierType qtAccessSpecifier;
0076 };
0077 
0078 using ClazySpecifierList = std::vector<ClazyAccessSpecifier>;
0079 
0080 class AccessSpecifierManager
0081 {
0082 public:
0083     explicit AccessSpecifierManager(ClazyContext *);
0084     void VisitDeclaration(clang::Decl *decl);
0085 
0086     /**
0087      * Returns if a method is a signal, a slot, or neither.
0088      */
0089     QtAccessSpecifierType qtAccessSpecifierType(const clang::CXXMethodDecl*) const;
0090 
0091     /**
0092      * Returns if a method is scriptable (Q_SCRIPTABLE)
0093      */
0094     bool isScriptable(const clang::CXXMethodDecl*) const;
0095 
0096     /**
0097      * Returns a string representations of a Qt Access Specifier Type
0098      */
0099     llvm::StringRef qtAccessSpecifierTypeStr(QtAccessSpecifierType) const;
0100 
0101     clang::SourceLocation firstLocationOfSection(clang::AccessSpecifier specifier,
0102                                                  clang::CXXRecordDecl *decl) const;
0103 
0104 private:
0105     ClazySpecifierList &entryForClassDefinition(clang::CXXRecordDecl*);
0106     const clang::CompilerInstance &m_ci;
0107     const clang::CXXRecordDecl *classDefinitionForLoc(clang::SourceLocation loc) const;
0108     std::unordered_map<const clang::CXXRecordDecl*, ClazySpecifierList> m_specifiersMap;
0109     AccessSpecifierPreprocessorCallbacks *const m_preprocessorCallbacks;
0110     const bool m_fixitsEnabled;
0111     bool m_visitsNonQObjects = false;
0112 };
0113 
0114 #endif