xref: /aosp_15_r20/external/clang/lib/Analysis/FormatStringParsing.h (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li #ifndef LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H
2*67e74705SXin Li #define LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H
3*67e74705SXin Li 
4*67e74705SXin Li #include "clang/AST/ASTContext.h"
5*67e74705SXin Li #include "clang/AST/Type.h"
6*67e74705SXin Li #include "clang/Analysis/Analyses/FormatString.h"
7*67e74705SXin Li #include "llvm/Support/raw_ostream.h"
8*67e74705SXin Li 
9*67e74705SXin Li namespace clang {
10*67e74705SXin Li 
11*67e74705SXin Li class LangOptions;
12*67e74705SXin Li 
13*67e74705SXin Li template <typename T>
14*67e74705SXin Li class UpdateOnReturn {
15*67e74705SXin Li   T &ValueToUpdate;
16*67e74705SXin Li   const T &ValueToCopy;
17*67e74705SXin Li public:
UpdateOnReturn(T & valueToUpdate,const T & valueToCopy)18*67e74705SXin Li   UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)
19*67e74705SXin Li     : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}
20*67e74705SXin Li 
~UpdateOnReturn()21*67e74705SXin Li   ~UpdateOnReturn() {
22*67e74705SXin Li     ValueToUpdate = ValueToCopy;
23*67e74705SXin Li   }
24*67e74705SXin Li };
25*67e74705SXin Li 
26*67e74705SXin Li namespace analyze_format_string {
27*67e74705SXin Li 
28*67e74705SXin Li OptionalAmount ParseAmount(const char *&Beg, const char *E);
29*67e74705SXin Li OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,
30*67e74705SXin Li                                       unsigned &argIndex);
31*67e74705SXin Li 
32*67e74705SXin Li OptionalAmount ParsePositionAmount(FormatStringHandler &H,
33*67e74705SXin Li                                    const char *Start, const char *&Beg,
34*67e74705SXin Li                                    const char *E, PositionContext p);
35*67e74705SXin Li 
36*67e74705SXin Li bool ParseFieldWidth(FormatStringHandler &H,
37*67e74705SXin Li                      FormatSpecifier &CS,
38*67e74705SXin Li                      const char *Start, const char *&Beg, const char *E,
39*67e74705SXin Li                      unsigned *argIndex);
40*67e74705SXin Li 
41*67e74705SXin Li bool ParseArgPosition(FormatStringHandler &H,
42*67e74705SXin Li                       FormatSpecifier &CS, const char *Start,
43*67e74705SXin Li                       const char *&Beg, const char *E);
44*67e74705SXin Li 
45*67e74705SXin Li /// Returns true if a LengthModifier was parsed and installed in the
46*67e74705SXin Li /// FormatSpecifier& argument, and false otherwise.
47*67e74705SXin Li bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E,
48*67e74705SXin Li                          const LangOptions &LO, bool IsScanf = false);
49*67e74705SXin Li 
50*67e74705SXin Li /// Returns true if the invalid specifier in \p SpecifierBegin is a UTF-8
51*67e74705SXin Li /// string; check that it won't go further than \p FmtStrEnd and write
52*67e74705SXin Li /// up the total size in \p Len.
53*67e74705SXin Li bool ParseUTF8InvalidSpecifier(const char *SpecifierBegin,
54*67e74705SXin Li                                const char *FmtStrEnd, unsigned &Len);
55*67e74705SXin Li 
56*67e74705SXin Li template <typename T> class SpecifierResult {
57*67e74705SXin Li   T FS;
58*67e74705SXin Li   const char *Start;
59*67e74705SXin Li   bool Stop;
60*67e74705SXin Li public:
61*67e74705SXin Li   SpecifierResult(bool stop = false)
Start(nullptr)62*67e74705SXin Li   : Start(nullptr), Stop(stop) {}
SpecifierResult(const char * start,const T & fs)63*67e74705SXin Li   SpecifierResult(const char *start,
64*67e74705SXin Li                   const T &fs)
65*67e74705SXin Li   : FS(fs), Start(start), Stop(false) {}
66*67e74705SXin Li 
getStart()67*67e74705SXin Li   const char *getStart() const { return Start; }
shouldStop()68*67e74705SXin Li   bool shouldStop() const { return Stop; }
hasValue()69*67e74705SXin Li   bool hasValue() const { return Start != nullptr; }
getValue()70*67e74705SXin Li   const T &getValue() const {
71*67e74705SXin Li     assert(hasValue());
72*67e74705SXin Li     return FS;
73*67e74705SXin Li   }
getValue()74*67e74705SXin Li   const T &getValue() { return FS; }
75*67e74705SXin Li };
76*67e74705SXin Li 
77*67e74705SXin Li } // end analyze_format_string namespace
78*67e74705SXin Li } // end clang namespace
79*67e74705SXin Li 
80*67e74705SXin Li #endif
81