xref: /llvm-project/clang/lib/AST/FormatStringParsing.h (revision 6c97f8898685d5d07f14e859b21fad1ffe5c39c2)
1*6c97f889SErik Pilkington //===----- FormatStringParsing.h - Format String Parsing --------*- C++ -*-===//
2*6c97f889SErik Pilkington //
3*6c97f889SErik Pilkington // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*6c97f889SErik Pilkington // See https://llvm.org/LICENSE.txt for license information.
5*6c97f889SErik Pilkington // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*6c97f889SErik Pilkington //
7*6c97f889SErik Pilkington //===----------------------------------------------------------------------===//
8*6c97f889SErik Pilkington //
9*6c97f889SErik Pilkington // This provides some shared functions between printf and scanf format string
10*6c97f889SErik Pilkington // parsing code.
11*6c97f889SErik Pilkington //
12*6c97f889SErik Pilkington //===----------------------------------------------------------------------===//
13*6c97f889SErik Pilkington 
14314fbfa1STim Northover #ifndef LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H
15314fbfa1STim Northover #define LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H
16314fbfa1STim Northover 
17314fbfa1STim Northover #include "clang/AST/ASTContext.h"
18314fbfa1STim Northover #include "clang/AST/Type.h"
19314fbfa1STim Northover #include "clang/AST/FormatString.h"
20314fbfa1STim Northover 
21314fbfa1STim Northover namespace clang {
22314fbfa1STim Northover 
23314fbfa1STim Northover class LangOptions;
24314fbfa1STim Northover 
25314fbfa1STim Northover template <typename T>
26314fbfa1STim Northover class UpdateOnReturn {
27314fbfa1STim Northover   T &ValueToUpdate;
28314fbfa1STim Northover   const T &ValueToCopy;
29314fbfa1STim Northover public:
UpdateOnReturn(T & valueToUpdate,const T & valueToCopy)30314fbfa1STim Northover   UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)
31314fbfa1STim Northover     : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}
32314fbfa1STim Northover 
~UpdateOnReturn()33314fbfa1STim Northover   ~UpdateOnReturn() {
34314fbfa1STim Northover     ValueToUpdate = ValueToCopy;
35314fbfa1STim Northover   }
36314fbfa1STim Northover };
37314fbfa1STim Northover 
38314fbfa1STim Northover namespace analyze_format_string {
39314fbfa1STim Northover 
40314fbfa1STim Northover OptionalAmount ParseAmount(const char *&Beg, const char *E);
41314fbfa1STim Northover OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,
42314fbfa1STim Northover                                       unsigned &argIndex);
43314fbfa1STim Northover 
44314fbfa1STim Northover OptionalAmount ParsePositionAmount(FormatStringHandler &H,
45314fbfa1STim Northover                                    const char *Start, const char *&Beg,
46314fbfa1STim Northover                                    const char *E, PositionContext p);
47314fbfa1STim Northover 
48314fbfa1STim Northover bool ParseFieldWidth(FormatStringHandler &H,
49314fbfa1STim Northover                      FormatSpecifier &CS,
50314fbfa1STim Northover                      const char *Start, const char *&Beg, const char *E,
51314fbfa1STim Northover                      unsigned *argIndex);
52314fbfa1STim Northover 
53314fbfa1STim Northover bool ParseArgPosition(FormatStringHandler &H,
54314fbfa1STim Northover                       FormatSpecifier &CS, const char *Start,
55314fbfa1STim Northover                       const char *&Beg, const char *E);
56314fbfa1STim Northover 
570ff50d49SMatt Arsenault bool ParseVectorModifier(FormatStringHandler &H,
580ff50d49SMatt Arsenault                          FormatSpecifier &FS, const char *&Beg, const char *E,
590ff50d49SMatt Arsenault                          const LangOptions &LO);
600ff50d49SMatt Arsenault 
61314fbfa1STim Northover /// Returns true if a LengthModifier was parsed and installed in the
62314fbfa1STim Northover /// FormatSpecifier& argument, and false otherwise.
63314fbfa1STim Northover bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E,
64314fbfa1STim Northover                          const LangOptions &LO, bool IsScanf = false);
65314fbfa1STim Northover 
66314fbfa1STim Northover /// Returns true if the invalid specifier in \p SpecifierBegin is a UTF-8
67314fbfa1STim Northover /// string; check that it won't go further than \p FmtStrEnd and write
68314fbfa1STim Northover /// up the total size in \p Len.
69314fbfa1STim Northover bool ParseUTF8InvalidSpecifier(const char *SpecifierBegin,
70314fbfa1STim Northover                                const char *FmtStrEnd, unsigned &Len);
71314fbfa1STim Northover 
72314fbfa1STim Northover template <typename T> class SpecifierResult {
73314fbfa1STim Northover   T FS;
74314fbfa1STim Northover   const char *Start;
75314fbfa1STim Northover   bool Stop;
76314fbfa1STim Northover public:
77314fbfa1STim Northover   SpecifierResult(bool stop = false)
Start(nullptr)78314fbfa1STim Northover   : Start(nullptr), Stop(stop) {}
SpecifierResult(const char * start,const T & fs)79314fbfa1STim Northover   SpecifierResult(const char *start,
80314fbfa1STim Northover                   const T &fs)
81314fbfa1STim Northover   : FS(fs), Start(start), Stop(false) {}
82314fbfa1STim Northover 
getStart()83314fbfa1STim Northover   const char *getStart() const { return Start; }
shouldStop()84314fbfa1STim Northover   bool shouldStop() const { return Stop; }
hasValue()85314fbfa1STim Northover   bool hasValue() const { return Start != nullptr; }
getValue()86314fbfa1STim Northover   const T &getValue() const {
87314fbfa1STim Northover     assert(hasValue());
88314fbfa1STim Northover     return FS;
89314fbfa1STim Northover   }
getValue()90314fbfa1STim Northover   const T &getValue() { return FS; }
91314fbfa1STim Northover };
92314fbfa1STim Northover 
93314fbfa1STim Northover } // end analyze_format_string namespace
94314fbfa1STim Northover } // end clang namespace
95314fbfa1STim Northover 
96314fbfa1STim Northover #endif
97